我以为我了解 Oracle 的 CONNECT BY
是如何工作的。
但后来我发现了这个。
select dual.*, CONNECT_BY_ISCYCLE from dual
connect by nocycle 1=1
and LEVEL <= 2
;
结果
DUMMY CONNECT_BY_ISCYCLE
X 0
X 0
但是
select dual.*, CONNECT_BY_ISCYCLE from dual
connect by nocycle 1=1
and LEVEL <= 2
and prior dummy = dummy
;
只产生 1 行
DUMMY CONNECT_BY_ISCYCLE
X 1
我希望得到与第一个查询相同的结果。
有人可以解释或指出我对此的解释吗?
这是在 Oracle Database 12c Release 12.1.0.1.0 - 64bit Production
最佳答案
Oracle 如何识别分层查询中的“循环”?
如果它被记录下来,它就没有做得很好。无论如何,我认为我们在 OTN 讨论中找到了正确且完整(并且非常简单)的答案:https://community.oracle.com/thread/3999985
无论如何:当您运行分层查询时,对于生成的每一行,Oracle 将查看 由 connect by
子句中的 PRIOR 运算符操作的列,并且仅针对这些列,以查看新生成的行是否与现有行匹配。
这就是为什么“select 5 from dual connect by level <= 100”有效,即使它生成相同的行 100 次。没有循环,因为“循环”只查看 CONNECT BY 中以 PRIOR 开头的列 - 但没有。
这也是为什么您会经常看到类似connect by [other conditions here] and prior sys_guid() is not null
的原因。 sys_guid()
永远不会为空;但是通过将它添加到 connect by
,非常重要的是使用 PRIOR
运算符,您可以确保永远不会有循环(因为每次调用都保证返回不同的值! ) 所以你可以通过 level
或其他方式的条件来打破“无限递归”,但不能通过“循环”的识别来打破。 (由于要检查这个额外的“列”,Oracle 永远不会看到循环。)
关于Oracle CONNECT BY 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44453043/