CTE递归 MAXRECURSION 遇到的问题

摘要:
使用SqlServer时,当需要递归时,通常使用CTE。但是当递归层的数量超过100时,或者当存在递归循环时。当执行时,递归的数量将达到100。在第一种情况下,当层数超过100时,例如,当它用于生成数字序列或日期时,将maxrecursion设置为-1不是问题。但如果它是一个无休止的循环,则需要检查数据和查询语句的逻辑。我想说的是,如果

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

当面对第一种情况,层数超过了100,比方说用于生成数列或者日期的时候,讲 maxrecursion 设置为 -1就可以解决,这个也不是问题。但是如果是死循环的话呢,就需要检查自己数据和查询语句的逻辑了。

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

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

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

 CTE递归 MAXRECURSION 遇到的问题第1张

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

在这个原因,所以你看到这个简单的例子里面,就不存在递归A~F的情况。

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

但是如果要控制递归次数的话,可以做一个小改动,就可以控制递归次数

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

这样的话,就可以控制递归次数了。这个小技巧还是挺实用的,分享给大家

免责声明:文章转载自《CTE递归 MAXRECURSION 遇到的问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇解决fiddler无法抓取本地部署项目的请求问题Layui 之自定义验证下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

js 递归获取子节点所有父节点,深度遍历获取第一个子树

前端需求。 递归 深度优先遍历算法 // 查找一个节点的所有父节点 familyTree (arr1, id) { var temp = [] var forFn = function (arr, id) { for (var i = 0; i < arr.length; i++) {...

Oracle 递归拼接字段

效果 sql SELECT LISTAGG(T.NAME, '/ ') WITHIN GROUP(ORDER BY LEVEL DESC) ASRESULT FROMS_WORK_RESOURSE T START WITH T.WORK_RESOURCE_NO = 323CONNECT BY PRIOR T.PARENT_WORK_RESOURCE...

马踏棋盘(递归算法)

#include <iostream.h>int board [8][8]={0};int Htry1[8]={-2,-1,1,2,2,1,-1,-2};int Htry2[8]={1,2,2,1,-1,-2,-2,-1};bool chech[8][8]={0};//标记位置是否已经被占用int n=1;//就算已走的步数void findw...

在Lambda表达式中进行递归调用

Lambda表达式是一个匿名的方法,在开发期我们是不知道其方法名是什么的,所以我们要怎么递归调用呢? 如果你看过我这文章《让您知道您的方法是被何“人”调用 》的话,你应该会“啊哈”的拍一下头脑,思路就出来了,没错!!就是直接用StackFrame获取当前执行的方法,然后直接Invoke即可。示例代码:     class Test    {       ...

递归获取树形结构数据某个节点下的所有子节点数据

/// <summary> /// 获取组织结构树 /// </summary> /// <param name="list"></param> /// <param name="id"></param>...

vue+elementui搭建后台管理界面(5递归生成侧栏路由)

有一个菜单树,顶层菜单下面有多个子菜单,子菜单下还有子菜单。。。 这时候就要用递归处理 1 定义多级菜单 修改 src/router/index.js 的 / 路由 { path: '/', redirect: '/dashboard', name: 'Container', component: Container,...