-1
select rtrim(regexp_substr (str, '[^|]*(.|$)', 1, level), '|') ASPLIT
from 
(select 'str 1|str 2|str 3' as str from dual)
connect by level <= length (regexp_replace (str, '[^|]+')) + 1

str 1
str 2
str 3

How to alter the parser separator ', ' ?

'str 1, str 2, str 3'

Dmitriy
  • 133
  • 3
  • 13

2 Answers2

1

You can just change the delimiter in the pattern:

select rtrim(regexp_substr (str, '[^,]*(.|$)', 1, level), ',') ASPLIT
from 
(select 'str 1, str 2, str 3' as str from dual)
connect by level <= length (regexp_replace (str, '[^,]+')) + 1;

Note that you do not want to change the one in the grouping, (.|$); in that context it's an OR operator not a literal character.

It's simpler to use the same pattern in the substring as you do in the replace (but note Gary_W's warning about this losing empty values with this pattern):

select trim(regexp_substr (str, '[^,]+', 1, level)) ASPLIT
from (select 'str 1, str 2, str 3' as str from dual)
connect by level <= length (regexp_replace (str, '[^,]+')) + 1;

ASPLIT            
-------------------
str 1              
 str 2             
 str 3             

But since you have spaces after the commas, you need to eliminate those; the simplest way is to get rid of leading and trailing spaces with trim. This also shows a variation on the connect by limit but either works (again, note the warning about this pattern):

select trim(regexp_substr (str, '[^,]+', 1, level)) ASPLIT
from (select 'str 1, str 2, str 3' as str from dual)
connect by regexp_substr (str, '[^,]+', 1, level) is not null;

ASPLIT            
-------------------
str 1              
str 2              
str 3              
Alex Poole
  • 183,384
  • 11
  • 179
  • 318
1

I must point out that using the regex of the format '[^,]+' to parse a string will give invalid results if there is a NULL element in the list and the position of the element in the list is important. Consider this where the 2nd element is NULL. The results make it seem the 2nd element is 'str 3' where really the 2nd element is NULL.

SQL> select trim(regexp_substr (str, '[^,]+', 1, level)) ASPLIT
     from (select 'str 1,, str 3' as str from dual)
     connect by level <= length (regexp_replace (str, '[^,]+')) + 1;

ASPLIT
-------------
str 1
str 3

Here's another way that handles the NULL list element:

SQL> select trim(regexp_substr (str, '(.*?)(,|$)', 1, level, NULL, 1)) ASPLIT
     from (select 'str 1,, str 3' as str from dual)
     connect by level <= regexp_count(str, ',') + 1;

ASPLIT
-------------
str 1

str 3

SQL>

See this post for more info too: Split comma separated values to columns in Oracle

Community
  • 1
  • 1
Gary_W
  • 9,933
  • 1
  • 22
  • 40
  • Good point. The OP's original query handles that, so the first query in my answer, does too - though it still needs to trim whitespace. I'd wondered why the patterns weren't the same in the original query, and that's probably why. Your pattern gets rid of the `rtrim()` in the OP's version, which makes life simpler. – Alex Poole Apr 13 '16 at 14:54