T-SQL为什么递归不要停止?

时间:2016-03-24 09:11:20

标签: sql sql-server recursion common-table-expression

为什么这种递归不会停止?

DECLARE @T TABLE( id INT )
INSERT INTO @T( id ) VALUES (1), (2)

WITH cte AS(
    SELECT id, 1 a FROM @T WHERE id = 1
    UNION ALL
    SELECT T.id, O.id
    FROM @T T outer apply( SELECT * FROM cte WHERE cte.id = T.id ) O
    WHERE O.id IS NULL
    )
SELECT * FROM cte

如果我使用临时表#cte并将重复递归部分 - 在一些迭代后将是0记录...

2 个答案:

答案 0 :(得分:1)

您从一行开始:

SELECT id, 1 a FROM @T WHERE id = 1  
1     1

第一次递归返回两行(基于CROSS APPLY),WHERE删除其中一行:

SELECT T.id, O.id
FROM @T T outer apply( SELECT * FROM cte WHERE cte.id = T.id ) O
WHERE O.id IS NULL

1     1     -- filtered
2     NULL  -- returned and used for next recursion

每次后续递归都会返回两行:

SELECT T.id, O.id
FROM @T T outer apply( SELECT * FROM cte WHERE cte.id = T.id ) O
WHERE O.id IS NULL

1     NULL  -- returned and used for next recursion
2     NULL  -- returned and used for next recursion

结果是正确的,它可能是您尝试应用的逻辑。

你到底想要做什么?按原样查询是没用的......

答案 1 :(得分:0)

我将此添加为评论,但我没有足够的声誉这样做。

递归CTE的锚成员定义是正确的。但不是递归成员定义。由于将始终为查询返回记录

SELECT T.id, O.id
FROM @T T outer apply( SELECT * FROM cte WHERE cte.id = T.id ) O
WHERE O.id IS NULL

递归继续下去。

尝试WHERE O.id IS NOT NULL

有关详细信息:Recursive CTEs MSDN