奇怪的 Oracle 行为 - 递归 CTE 中的交叉连接适用于逗号但不适用于交叉连接子句

Weird Oracle behaviour - cross join in recursive CTE works with comma but not with cross join clause

假设下面的简单递归查询r 列出了几个数字。当查询的递归部分与不必要的 1 行 table 使用逗号分隔的旧方法交叉连接时,一切正常 (dbfiddle):

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 错误 (dbfiddle):

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(我的项目 db)和 Oracle 18(dbfiddle)。最小化案例,本来是对图数据的分层查询,其中2行代表边缘端点的辅助关系以这种方式交叉连接。

我可以(不情愿地)接受第一种语法,尽管我对黑暗的无证角落或 Oracle 构建查询有不好的感觉。我没有找到这种行为的任何理由,也没有找到错误的踪迹。有人知道吗?谢谢。

使用第一个递归查询,你会得到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; 

可以加循环子句解决:

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;

给出了要求的结果。

到目前为止,我找到的最接近的解释是在 this thread on MOS 中。在线程中,OP 在 where 子句中使用具有连接条件的内部连接有效地连接表。在 from 子句中,只有两个表用 cross join 或逗号连接。我的示例在 dual table 不涉及任何连接条件方面有所不同,这削弱了线程中的一些推理,例如 任何涉及 2 个不同表的内容都被识别为连接条件

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

为了这个问题我在MOS上设置了own thread。还有答案怀疑是错误,但没有更清楚的解释。

总结:目前尚不清楚它是错误还是某些未记录的功能。在 where 子句中用逗号分隔和连接条件似乎是这种情况下最安全的方法。