2017-07-11 18 views
0

与普通表表达式又名with条款下工作的,我们可以命名一个子查询,并参考来自于我们的SQL语句中的任何位置这个子查询。更有意思的是,我们可以从查询本身引用查询,从而实现递归,这使得SQL可以完成语言。WITH子句Oracle中递归如何引擎盖

这个概念很简单,但我感兴趣的是如何在技术上甲骨文实现了调用堆栈,行和评价的渴望期限递归方面。

这里是行动递归with条款的简单例子。它是强制递归的with子句由两个成员组成:锚成员(初始行)和递归成员,由union all运算符组合。

with numbers(val) as (
    select 1 as val from dual 
    union all 
    select val + 1 from numbers 
    where val < 5 
) 
select val from numbers 

将会产生

VAL 
-- 
1 
2 
3 
4 
5 

如何调用堆栈积累的结果集“看起来像”在这个例子吗?是否所有的逻辑结构是如何从SQL语句中得出的,但我只是不明白,或者Oracle有什么神奇的东西来解释这个语句来实现递归吗?

另外,为什么限制因素(where子句)必须是在递归构件本身,而不是其中使用CTE?下面的尝试引发错误

with numbers(val) as (
    select 1 as val from dual 
    union all 
    select val + 1 from numbers 
) 
select val from numbers where val < 5 

和错误是

ORA-32044: cycle detected while executing recursive WITH query 

这是否意味着Oracle不支持与公共表表达式懒惰的评价?相比之下,PostgreSQL中的以下工作。

WITH RECURSIVE t(v) AS (
    SELECT 1  -- Seed Row 
    UNION ALL 
    SELECT v + 1 -- Recursion 
    FROM t 
) 
SELECT v 
FROM t 
LIMIT 5 

这让我想起了使用终端操作进行懒惰评估的更多数据。这里与Oracle有什么技术区别?

回答

0

我必须承认我对理解你的问题有困难。递归查询是这样构建的:

<start query> 
UNION ALL 
<next query> 

的<开始查询>被执行和检索行。对于这些行中的每一行,<下一个查询>被执行,产生更多行。并且对于每个新创建的行<,将再次执行下一个查询>,依此类推,直到WHERE子句中的条件不再满足。

您创建值为1的行然后创建一个新的行用1 + 1 = 2。然后你创建一个2 + 1 = 3的新行。然后创建一个3 + 1 = 4的新行。然后你创建一个4 + 1 = 5的新行。并且你停下来,因为5不符合标准value < 5

如果去掉WHERE子句,递归查询应该无休止地运行。我不明白这里的ORA错误,因为你永远不会进入一个循环,因为这个值总是在增加。您可能会耗尽内存或超出允许的最大整数值,但不会进入循环。所以我认为错误信息是误导性的。

如果PostgreSQL在这里使用懒惰评估,你很幸运。我不认为他们保证会发生这种情况。总是有一个WHERE子句来结束你递归中的递归。