我正在尝试使用下面的查询生成Fibonacci系列(递归WITH子句)。
WITH X(Pnbr,Cnbr) AS
(SELECT 0, 1 FROM dual
UNION ALL
SELECT X.Cnbr, X.Pnbr+X.Cnbr FROM X
WHERE X.Cnbr<50
)
SELECT * FROM X
但我收到此错误
ORA-32044: cycle detected while executing recursive WITH query
为什么?
答案 0 :(得分:5)
您在第一次迭代时的数据将是
PNBR CNBR
0 , 1
1 , 1 + 0
所以,CNBR是1是前两行..检测到循环!
CONNECTING
条件必须唯一!
所以你可能需要维护一个迭代器。
ROWNUM
就是我在这里使用的。
WITH X(iter,Pnbr,Cnbr) AS
(SELECT 1,0, 1 FROM dual
UNION ALL
SELECT iter + rownum, X.Cnbr, X.Pnbr+X.Cnbr FROM X
WHERE iter < 50
)
SELECT iter,Pnbr FROM X;
答案 1 :(得分:0)
我同意M. Ravisankar的回答(从2015年开始)中的诊断,但不同意该疗法。
为精确处理原始帖子中提出的情况,递归CTE提供了CYCLE
子句。在此问题中,尽管Pnbr
列和Cnbr
列中都有重复的值,但当单独考虑时,复合中没有重复的值(重复项) (Pnbr, Cnbr)
。
因此,查询可以这样写:
WITH X(Pnbr,Cnbr) AS
(SELECT 0, 1 FROM dual
UNION ALL
SELECT X.Cnbr, X.Pnbr+X.Cnbr FROM X
WHERE X.Cnbr<50
)
cycle Pnbr, Cnbr set cycle to 'Y' default 'N' ----
SELECT Pnbr, Cnbr FROM X
注意cycle
子句(倒数第二行),也注意SELECT Pnbr, Cnbr
而不是SELECT *
(如果在此处选择*,我们还将得到cycle
列,我们不需要)。
答案 2 :(得分:0)
修改where子句中的列。使用X.Pnbr+X.Cnbr
代替X.Cnbr
作为条件,以便Oracle将两个引用的列用于行循环检测。
WITH X(Pnbr,Cnbr) AS
(SELECT 0, 1 FROM dual
UNION ALL
SELECT X.Cnbr, X.Pnbr+X.Cnbr FROM X
-- Cnbr column is used to detect the cycle data
WHERE X.Pnbr+X.Cnbr < 50
)
SELECT * FROM X;
根据Oracle Doc:
如果省略CYCLE子句,则如果发现循环,则递归WITH子句将返回错误。在这种情况下,如果行的祖先行之一对递归成员的WHERE子句中引用的query_name的列别名列表中的所有列具有相同的值,则该行将形成循环。
查询输出: