使用Oracle Regexp_Replace从字符串中删除重复的嵌套短语

icomxhvb  于 2022-09-18  发布在  Java
关注(0)|答案(1)|浏览(282)

作为PL/SQL脚本的一部分,我们将设置一个名为‘V_COMMENT’的VAXIR变量:

V_COMMENT := INCOMING_COMMENT || '[' || V_COMMENT || ']';

由于此语句可能为每条记录运行多次,因此我们最终将得到如下注解:

进程578[进程456[进程123]]

有一个问题,当您重新运行此脚本时,有时可能会添加重复的标记:

进程123[进程123[进程000]]

进程456[进程123[进程123]]

其中,注解被重复和嵌套。

有没有办法使用Regexp_Replace()来删除重复的标记,不管是嵌套的还是其他的?

或者另选地

有没有办法用regexp_like捕捉这些错误注解的出现

8hhllhi2

8hhllhi21#

您可以使用下面的解决方案删除重复的评论。事实上,我在pl/SQL中使用动态SQL来解决这个问题。

DECLARE
v_comment CLOB ;
v_comment2 CLOB ; 
v_sql CLOB;

BEGIN
--V_COMMENT := INCOMING_COMMENT || '[' || V_COMMENT || ']'; 
v_comment := 'process 456[process 123[process 123[process 456[process 000]]]]' ;

v_sql := q'{
with v_temp1 as (
  select '}'||v_comment||q'{' as comm0 from dual
  )
 , v_temp2 AS (
  select comm0
       , LEVEL lvl
       , regexp_count(comm0, '[^[]+') cnt
       , trim(rtrim( regexp_substr(comm0, '[^[]+', 1, LEVEL), ']' )) AS comm1
       , row_number()OVER(PARTITION BY comm0, trim(rtrim( regexp_substr(comm0, '[^[]+', 1, LEVEL), ']' ))  ORDER BY LEVEL) rnb
  from v_temp1
  CONNECT BY LEVEL <= regexp_count(comm0, '[^[]+')
 )
  SELECT listagg(comm1, '[') WITHIN GROUP (ORDER BY lvl) || 
         LPAD(']', regexp_count(listagg(comm1, '[')WITHIN GROUP (ORDER BY lvl), '['), ']') comm2
  FROM v_temp2
  WHERE rnb = 1
}'
;

--dbms_output.put_line(v_sql); --test

execute immediate v_sql into v_comment2
;

dbms_output.put_line('input v_comment : ' ||v_comment ); --test
dbms_output.put_line('output v_comment2 : '||v_comment2); --test
END;
/

demo : pl/sql

以下是我的解决方案中的SQL部分:

with v_temp1 as (
  select 'process 578 [process 456 [process 123]]' comm0 from dual union all
  select 'process 123 [process 123 [process 000]]' from dual union ALL
  select 'process 456 [process 123 [process 123 [process 456 ]]]' from dual
  )
 , v_temp2 AS (
  select comm0
       , LEVEL lvl
       , regexp_count(comm0, '[^[]+') cnt
       , trim(rtrim( regexp_substr(comm0, '[^[]+', 1, LEVEL), ']' )) AS comm1
       , row_number()OVER(PARTITION BY comm0, trim(rtrim( regexp_substr(comm0, '[^[]+', 1, LEVEL), ']' ))  ORDER BY LEVEL) rnb
  from v_temp1
  CONNECT BY LEVEL <= regexp_count(comm0, '[^[]+')
  /*You need to add the following two conditions when processing more than one row*/
  AND PRIOR comm0 = comm0
  AND PRIOR sys_guid() IS NOT NULL
 )
  SELECT comm0, listagg(comm1, '[') WITHIN GROUP (ORDER BY lvl) || 
         LPAD(']', regexp_count(listagg(comm1, '[')WITHIN GROUP (ORDER BY lvl), '['), ']') comm2
  FROM v_temp2
  WHERE rnb = 1
  GROUP BY comm0
;

demo : sql

相关问题