CTE递归 MAXRECURSION 遇到的问题

在使用Sql Server的时候,当须要递归的时候不少时候就会想到使用CTE。可是当递归层数比较多,超过了100层,或者是一个递归死循环的时候。执行就会爆递归次数已到,最多100的错误。数据库

当面对第一种状况,层数超过了100,比方说用于生成数列或者日期的时候,讲 maxrecursion 设置为 -1就能够解决,这个也不是问题。可是若是是死循环的话呢,就须要检查本身数据和查询语句的逻辑了。spa

这里我要说的是,假如咱们在查询的时候手动设置 maxrecursion  的时候,能不能避免死循环,只循环到某一层呢?3d

先给答案,是不行的,而后上例子,显而易见,这里确定是一个死循环,而后返回结果是酱纸的。code

IF OBJECT_ID('tempdb..#ID') IS NOT NULL
    DROP TABLE #ID

CREATE TABLE #ID (ID INT,vname VARCHAR(50))

INSERT INTO #ID
        ( ID, vname )
VALUES  ( 1, 'A'),(2,'B'),(3,'B'),(4,'B'),(5,'B'),(6,'B'),(7,'B')

;WITH CTE AS
(
    SELECT * FROM #ID
    UNION ALL
    SELECT ID+1,CTE.vname
        FROM CTE 
)

SELECT * FROM CTE

 

显示出来第一层,而后就是一直递归最后一条数据。能够看出来,并非每一条数据手牵手递归一层,而后又手牵手递归一层的效果,而是先游标递归完最后一条,而后反推回来最上面一条的。blog

在这个缘由,因此你看到这个简单的例子里面,就不存在递归A~F的状况。递归

好,而后回答前面的问题,使用 maxrecursion 的值来控制递归次数是不可取的,惟一有用的地方就是减小了递归次数,有效减小数据库的开销。io

可是若是要控制递归次数的话,能够作一个小改动,就能够控制递归次数class

IF OBJECT_ID('tempdb..#ID') IS NOT NULL
    DROP TABLE #ID

CREATE TABLE #ID (ID INT,vname VARCHAR(50))

INSERT INTO #ID
        ( ID, vname )
VALUES  ( 1, 'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E'),(6,'F'),(7,'G')

;WITH CTE AS
(
    SELECT *,1 AS Lv FROM #ID
    UNION ALL
    SELECT ID+1,CTE.vname,Lv+1
        FROM CTE 
        WHERE CTE.Lv < 3
)

SELECT * FROM CTE

 

这样的话,就能够控制递归次数了。这个小技巧仍是挺实用的,分享给你们循环

相关文章
相关标签/搜索