CTE递归 MAXRECURSION 遇到的问题

本文探讨了在 SqlServer 中使用 CTE 进行递归查询时遇到的问题,特别是如何避免递归超过100层或死循环的情况。通过调整 maxrecursion 参数和增加层级计数字段,实现了递归层数的有效控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

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

转载于:https://www.cnblogs.com/Gin-23333/p/6957838.html

库存消耗明细 AS ( -- 初始化:为每个销售创建独立处理链路 SELECT s.product_sku, s.销售时间, s.销售数量 AS 初始销售需求, LEAST(i.库存数量, s.销售数量) AS 已消耗数量, s.销售数量 - LEAST(i.库存数量, s.销售数量) AS 剩余销售需求, i.库龄阶段, i.库存数量, i.库存顺序 AS 当前库存顺序, s.销售顺序, 1 AS 是否新销售 FROM 排序后销售 s INNER JOIN 排序后库存 i ON s.product_sku = i.product_sku AND i.库存顺序 = 1 -- 从第一个库存阶段开始 UNION ALL -- 递归:持续消耗当前销售的库存,直到需求满足或库存耗尽 SELECT c.product_sku, c.销售时间, c.初始销售需求, c.剩余销售需求, i.库龄阶段, i.库存数量, i.库存顺序 AS 当前库存顺序, c.销售顺序, c.已消耗数量, 0 AS 是否新销售 FROM 库存消耗明细 c INNER JOIN 排序后库存 i ON c.product_sku = i.product_sku AND i.库存顺序 = c.当前库存顺序 + 1 -- 关键:递进到下一个库存阶段 WHERE c.剩余销售需求 > 0 AND i.库存数量 > 0 )我不了解为什么要把'0-3天'转数字,我是通库存顺序去匹配库存阶段的,库存阶段也是通过CASE WHEN inventory_days >= 0 AND inventory_days <= 30 THEN '0-30天' WHEN inventory_days >= 31 AND inventory_days <= 60 THEN '31-60天' WHEN inventory_days >= 61 AND inventory_days <= 90 THEN '61-90天' WHEN inventory_days >= 91 AND inventory_days <= 120 THEN '91-120天' WHEN inventory_days >= 121 AND inventory_days <= 180 THEN '121-180天' WHEN inventory_days >= 181 AND inventory_days <= 270 THEN '181-270天' WHEN inventory_days >= 271 AND inventory_days <= 360 THEN '271-360天' WHEN inventory_days >= 361 AND inventory_days <= 630 THEN '361-630天'得来的
03-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值