奇怪的 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
子句中用逗号分隔和连接条件似乎是这种情况下最安全的方法。
假设下面的简单递归查询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
子句中用逗号分隔和连接条件似乎是这种情况下最安全的方法。