尝试使用递归WITH子句生成Fibonacci系列,得到错误:'在执行'时检测到循环。

时间:2015-05-09 05:20:45

标签: sql oracle recursion

我正在尝试使用下面的查询生成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

为什么?

3 个答案:

答案 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;

DEMO

答案 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的列别名列表中的所有列具有相同的值,则该行将形成循环。

查询输出:

Executing Result