CTE是如何进行递归的?产生递归的条件有三个,分别是
- 初始值
- 自身调用自身
- 结束递归的条件
1,示例代码
;with cte as ( select 1 as id, 1 as jd union all select id +1 as id ,jd+2 as jd from cte where id<10 ) select * from cte
查询结果如下
2,递归过程分析
2.1 初始值
select 1 as id, 1 as jd 提供初始值,CTE中的值只有这一个。
2.2 第一次递归调用
select id +1 as id ,jd+2 as jd
from cte
where id<10
在第一次递归时,Cte的值只有初始值,递归调用之后, id=2,jd=3
2.3 第二次递归调用
第二次递归调用时,递归调用的CTE的值是 id=2, jd=3,递归调用之后,获得一个新行,id=3,jd=5
依次类推,每一次递归使用的CTE的值都是上一次递归改变的值。
2.4 递归结束
where id<10 ,递归结束之后,将所有的CTE的值进行 union all
递归结束的条件是 select 子句返回的查询结果为null,或达到maxrecursion的限制,即递归最大嵌套次数。
3,CTE 的最大递归次数
TSql默认的递归次数是100,也可以通过option提示来修改允许的递归次数。
;with cte as ( select 1 as id, 1 as jd union all select id+1 as id, jd+2 as jd from cte --where id<10 ) select * from cte option(maxrecursion 10)
如果要允许无限制的递归嵌套,必须使用嵌套提示 option(maxrecursion 0)
当在查询执行期间达到指定或默认的 MAXRECURSION 数量限制时,Sql Server将结束查询并返回错误,如下
Msg 530, Level 16, State 1, Line 2
The statement terminated. The maximum recursion 10 has been exhausted before statement completion.
由于此错误,该语句的所有结果都被回滚。如果该语句为 SELECT 语句,则可能会返回部分结果或不返回结果。所返回的任何部分结果都可能无法包括超过指定最大递归级别的递归级别上的所有行。
所以,慎用maxrecursion 查询提示,在正式的代码中,不要使用。在测试代码中通过之后,去掉maxrecursion,通过where 条件来限制递归嵌套的次数。