奇怪的Oracle行为--递归CTE中的交叉连接与逗号一起使用,但与交叉连接子句不一样

问题描述 投票:0回答:1

假设以下简单的递归查询 r 来列出几个数字。当递归查询的部分与不需要的1行表交叉连接时,使用旧的方式,用逗号分隔,一切都很好 (哑谜):

with r (x) as (
  select 1 as x from dual
  union all
  select x + 1 from r,dual where x < 5
)
select * from r

如果我把逗号改为 cross join 句,我得到 ORA-32044: cycle detected while executing recursive WITH query哑谜):

with r (x) as (
  select 1 as x from dual
  union all
  select x + 1 from r cross join dual where x < 5
)
select * from r;

在Oracle 11g(我的项目数据库)和Oracle 18(dbfiddle)上转载。这个案例是最小化的,原本是对图数据的分层查询,其中有2行代表边缘端点的辅助关系以这种方式交叉连接。

我可以(不愿意)忍受第一种语法,虽然我有不好的感觉,黑暗的未记录的角落或Oracle建立查询。我没有找到任何理由,这样的行为,也没有跟踪的错误。有人知道吗?谢谢。

oracle cycle recursive-query cross-join
1个回答
2
投票

使用第一个递归查询,你会得到5条记录,当你尝试对递归结果进行交叉连接时,每次迭代数据时,根据5的值,每次迭代的值都会相互循环,导致。ORA-32044: cycle detected while executing recursive WITH query 错误。相反,你必须在递归结果的一侧进行交叉连接,如下所示。

with r (x) as (
  select 1 as x from dual
  union all
select x + 1 from r,dual where x < 5
)
select * from r
cross join r; 

2
投票

你可以添加循环子句来解决。

with r (x) as (
      select 1 as x from dual
      union all
      select x + 1   from r cross join dual where x < 5
    ) cycle x set is_cycle to 1 default 0 
    select * from r;

给予所需的结果。


1
投票

到目前为止,我找到的最接近的解释是在 这条 在MOS上。在这个线程中,OP用内联接的方式有效地联接了表,联接条件是在 where 条款。在 from 子句,只有两个表连接,要么 cross join 或逗号。我的例子在以下方面有所不同 dual table 不涉及任何连接条件,这削弱了线程中的一些推理,如 凡是涉及到两个不同的表,都会被认为是连接条件.

总之,似乎Oracle实际上将逗号分隔的表评估为内部连接,这--由于某些未知的原因--在递归循环的评估中的顺序不同。如果我把连接条件改为内联接为真----。from r inner join dual on r.x = r.x - 的查询也成功了,这就支持了这个猜测。

我设置了 自己的线 MOS上的这个问题。也有怀疑是bug的回答,但没有更明确的解释。

小结:目前还不清楚这到底是一个bug还是一些未被记录的功能。逗号和连接条件下的分隔 where 在这种情况下,条款似乎是最安全的方式。

© www.soinside.com 2019 - 2024. All rights reserved.