ORACLE CONNECT BY LEVEL 生成重复行

use*_*642 3 regex sql oracle

我正在尝试从由附加到 varchar(4000) 列的多个注释组成的字符串中提取数据。我在查询中混合使用了正则表达式和函数,并使用 regexp_count 进行按级别连接,因为我不知道是否会有一个注释或多个注释。当我返回结果时,我注意到有很多重复的行。我相信这纯粹是由于 CONNECT BY 造成的,而且我以前没有使用过它,所以我认为我错过了一些东西。

这是查询;

    select 
  id,
  substr(regexp_substr(VALUE,'^LOCKED BY USER: +(.*)',1,level,'m'),17) as LOCKUSER,
  substr(regexp_substr(VALUE,'^LOCKED ENTITY: +(.*)',1,level,'m'),16) as LOCKED_ENTITY,
  TO_DATE(LTRIM(regexp_substr(VALUE,'^LOCKED AT: ([[:digit:]]{2}/[[:digit:]]{2}/[[:digit:]]{4}\.?)',1,level,'m'),'LOCKED AT: '),'DD/MM/YYYY') as Dates_Locked,
  substr(regexp_substr(VALUE,'^LOCK NOTES: +(.*)',1,level,'m'),13) as LOCK_NOTES,
  'LOCK' as ACTION
 from TABLE
 where regexp_substr(VALUE,'^LOCK NOTES: +(.*)',1,level,'m') IS NOT NULL
  AND TO_DATE(LTRIM(regexp_substr(VALUE,'LOCKED AT: ([[:digit:]]{2}/[[:digit:]]{2}/[[:digit:]]{4}\.?)',1,level,'m'),'LOCKED AT: '),'DD/MM/YYYY') >= (SYSDATE -365)
connect by level <= regexp_count(VALUE,CHR(10)||CHR(13));
Run Code Online (Sandbox Code Playgroud)

如果我让它针对一个有 10K 记录的表运行,我永远不会得到任何结果,我认为这是由于它返回的重复行的数量巨大。我有办法阻止这种情况吗?

非常感谢

Dav*_*sta 7

目前,您CONNECT BY仅限制层次级别,并且不提供任何将子行与父行匹配的条件。这意味着在具有多行的表中,每一行都是所有其他行的子行。这将产生大量的结果集。

如果我理解正确,您正在尝试使用分层功能从每个单独的行中提取多个值。所以你真的希望每一行都是它自己的父行和子行。我建议尝试:

CONNECT BY id = PRIOR id
AND prior sys_guid() is not null
AND level <= regexp_count(VALUE,CHR(10)||CHR(13))
Run Code Online (Sandbox Code Playgroud)

感谢 @kfinity 指出需要 sys_guid() 来防止 CONNECT BY LOOP。

  • 如果您收到 ORA-01436,您可能还需要添加“and previous sys_guid() is not null” (3认同)