Convert delimited string to rows in oracle [duplicate]

风流意气都作罢 提交于 2020-01-14 05:54:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!