zoukankan      html  css  js  c++  java
  • CTE递归 MAXRECURSION 遇到的问题

    在使用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

     

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

    在这个原因,所以你看到这个简单的例子里面,就不存在递归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

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

  • 相关阅读:
    使用.NET程序操作已打开的excel文件
    Ruby 加密(md5,sha1,base64)
    ThinkPad机型Hotkey影响QQ停靠在桌面边缘时自动隐藏功能
    IE6 下 的 a:hover
    下载 针式个人知识库管理软件 V9.08 版
    从智能手机App来看C/S和B/S的区别在哪?(Web的技术本质)
    分库分表的设计思路让大系统变简单
    会员充值消费管理系统
    解决WebDev.Webserver4(.net 4) 只能用于本机调试的问题
    WebApplication 完全编译即aspx不可修改,不包括设计内容的方法
  • 原文地址:https://www.cnblogs.com/Gin-23333/p/6957838.html
Copyright © 2011-2022 走看看