在Oracle中每第3次出现逗号后打印所有字符

时间:2018-07-26 06:31:47

标签: xml oracle oracle11g

我有一个字符串,例如“ 12as3,45we6,7we89,101112,131415,3234,1234”,并且想编写一个oracle regex函数或SQL以在每第3次出现逗号(,)后打印所有字符。 / p>

因此,此输出应为

12as3,45we6,7we89
101112,131415,3234
1234

我尝试过正则表达式,但它仅打印第一次出现的情况。

 SELECT NVL(
  SUBSTR('12as3,45we6,7we89,101112,131415,3234,1234', 1,
  INSTR('12as3,45we6,7we89,101112,131415,3234,1234',',',1,3) -1),
 '12as3,45we6,7we89,101112,131415,3234,1234')
FROM dual;

输出是  12as3,45we6,7we89

我也尝试过这种方法,但是每次逗号后都会打印。

with t as (
       select '12as3,45we6,7we89,101112,131415,3234,1234' as str from dual
      )
select  extractvalue(value(x), '/b') x
from  t,
    table(
          xmlsequence(
                      xmltype('<a><b>' || replace(str, ',', '</b><b>') || 
 '</b></a>' ).extract('/*/*')
                     )
             ) x
    /

有没有不用功能程序的方法,我们可以在Oracle中写一条select语句。

1 个答案:

答案 0 :(得分:1)

这里是使用功能的一个选项。

想法是:

  • 将输入字符串分成行
  • 将它们的片段(一个)以3个为一组,并以逗号分隔
  • 如果它是第三块(请参见MOD功能),请用换行符(CHR(10))(这是 splitter )将它们分开 li>

SQL> create or replace function f_split (par_str in varchar2)
  2    return varchar2
  3  is
  4    l_str varchar2(200);
  5  begin
  6    for cur_r in (select mod(row_number() over (order by null), 3) rn_mod,
  7                         case when mod(row_number() over (order by null), 3) = 0 then chr(10)
  8                              else ','
  9                         end splitter,
 10                         regexp_substr(par_str, '[^,]+', 1, level) one
 11                  from dual
 12                  connect by level <= regexp_count(par_str, ',') + 1
 13                 )
 14    loop
 15      l_str := l_str || cur_r.one || cur_r.splitter;
 16    end loop;
 17
 18    return (l_str);
 19  end;
 20  /

Function created.

SQL> select f_split('12as3,45we6,7we89,101112,131415,3234,1234') result from dual;

RESULT
--------------------------------------------------------------------------------
12as3,45we6,7we89
101112,131415,3234
1234,


SQL>

为什么不使用相同代码的简单SQL?因此:

SQL> with test (col) as
  2    (select '12as3,45we6,7we89,101112,131415,3234,1234' from dual),
  3  split_me as
  4    (select row_number() over (order by null) rn,
  5            case when mod(row_number() over (order by null), 3) = 0 then chr(10)
  6                 else ','
  7            end splitter,
  8            regexp_substr(col, '[^,]+', 1, level) one
  9     from test
 10     connect by level <= regexp_count(col, ',') + 1
 11    )
 12  select listagg(one, splitter) within group (order by rn) result
 13  from split_me;
select listagg(one, splitter) within group (order by rn) result
                    *
ERROR at line 12:
ORA-30496: Argument should be a constant.


SQL>

我不知道该如何解决。