问题
I used to use below query to convert comma delimited string to rows -
select regexp_substr('A,B,C,D','[^,]+', 1, level) from dual
connect by regexp_substr('A,B,C,D', '[^,]+', 1, level) is not null;
But, now my delimiter is - '~^'
I am not able to use same query for this delimiter.
select regexp_substr('A~^B~^C~D^E','[^~^]+', 1, level) from dual
connect by regexp_substr('A~^B~^C~D^E', '[^~^]+', 1, level) is not null;
I expect -
Column
A
B
C~D^E
Please help
OR May be is it possible to get nth element if delimiter provided is ~^
Best Regards
回答1:
Riffing off this method for splitting a string while allowing for nulls:
select regexp_substr('A~^B~^C~D^E','(.*?)(~\^|$)', 1, level, null, 1) from dual
connect by level < regexp_count('A~^B~^C~D^E','(.*?)(~\^|$)');
REGEXP_SUBS
-----------
A
B
C~D^E
As in the linked answer it looks for any characters, non-greedily, followed by the combination of ~^
(with the caret escaped, so ~\^
) or end-of-line. The regexp_substr()
calls also uses the optional arguments to specify subexpr
- so it only gets the first grouping (.*?
) and not the delimiter itself, which is in the second grouping.
If you want a specific element then that's even closer to the linked post:
select regexp_substr('A~^B~^C~D^E','(.*?)(~\^|$)', 1, 3, null, 1) from dual;
REGEX
-----
C~D^E
Or as you're doing this in a procedure, use the connect-by query to populate a collection, and then pick out the element you need, if you'll be looking at more than one.
回答2:
I can't do it with regexp functions - too hard! How about this bespoke function?
create or replace function test (p_str varchar2, p_delim varchar2)
return SYS.KU$_VCNT -- handy table of VARCHAR2(4000) in SYS
is
l_str long := p_str;
l_ret SYS.KU$_VCNT := SYS.KU$_VCNT();
begin
while instr (l_str, p_delim) > 0 loop
l_ret.extend;
l_ret(l_ret.count) := substr(l_str, 1, instr (l_str, p_delim)-1);
l_str := substr (l_str, instr (l_str, p_delim)+2);
end loop;
if l_str is not null then
l_ret.extend;
l_ret(l_ret.count) := l_str;
end if;
return l_ret;
end;
Then:
select * from table (test('A~^B~^C~D^E','~^'));
A
B
C~D^E
nth element (e.g. 2nd):
select column_value from
(select column_value, rownum n from table (test('A~^B~^C~D^E','~^')))
where n = 2;
回答3:
Hmmm . . . This comes very close:
select regexp_substr('A~^B~^C~D^E', '([^~]|[~][^^])+', 1, level) from dual
connect by regexp_substr('A~^B~^C~D^E', '([^~]|[~][^^])+', 1, level) is not null
You can get rid of the ^
by doing:
select regexp_replace(regexp_substr('A~^B~^C~D^E', '([^~]|[~][^^])+', 1, level), '^\^', '') from dual
connect by regexp_substr('A~^B~^C~D^E', '([^~]|[~][^^])+', 1, level) is not null
来源:https://stackoverflow.com/questions/45672769/convert-delimited-string-to-rows-in-oracle