【问题标题】:T-SQL: simple recursion exceeding max recursion depthT-SQL:超过最大递归深度的简单递归
【发布时间】:2018-11-27 13:39:16
【问题描述】:

我有一张表格my_table


rowNumber    number   ...
1               23
2               14
3               15
4               25
5               19
6               21
7               19
8               37
9               31
        ...
1000            28
我想找到number 列的递增连续序列的最大长度。对于此示例,它将是 3:
14, 15, 25

我的想法是为每个数字计算这样的长度:


rowNumber    number   ...   length
1               23            1
2               14            1
3               15            2
4               25            3
5               19            1
6               21            2
7               19            1
8               37            2
9               31            1
        ...
然后取最大值。为了计算length,我编写了以下使用递归的查询:

with enhanced_table as (select *
                               ,1 length
                       from    my_table 
                       where   rowNumber = 1
                       union all
                       (select b.*
                               ,case when b.number > a.number 
                                     then a.length + 1 
                                     end new_column
                       from    enhanced_table a, my_table b 
                       where   b.rowNumber = a.rowNumber + 1
                       )
select  max(length)
from    enhanced_table
所以,我试图从rowNumber = 1 开始,并通过递归连续添加所有其他行。我收到maximum recursion 100 has been exhausted before statement completion 错误。

我的问题是:我应该找到一种方法来增加服务器上允许的最大迭代次数(鉴于查询很简单,我认为运行 1000 次迭代不会有问题),还是找到另一种方法?

另外,100 次迭代是不是太低了阈值?

谢谢!

【问题讨论】:

  • 您应该避免在存储过程中使用递归代码,除非您绝对确定深度永远不会超过“几个”。如果不止于此,您必须假设它会在某个时候达到极限并死亡。

标签: sql-server recursion exceed


【解决方案1】:

如果您希望在查询开头声明 maxrecursion 参数。 您可以尝试构建查询,例如:

    DECLARE @Query NVARCHAR(MAX)
    SET @Query = N'
    ;WITH foo AS (
        ...
     )

    SELECT * FROM foo
    OPTION (MAXRECURSION ' + CAST(@maxrec AS NVARCHAR) + ');'

并使用 Exec 执行它

你可以去这里参考这个答案:Maxrecursion parameter

【讨论】:

    【解决方案2】:

    必须有一些默认阈值,这就是微软选择的。这是为了防止无限循环。此外,循环在 SQL Server 中表现不佳,并违背其基于集合的结构。

    您可以指定要为单个查询设置的最大递归。这会覆盖默认值。

    select  max(length)
    from    enhanced_table
    option (maxrecursion 1000)
    

    注意,选项 (maxrecursion 0) 与无限制...相同,可能导致无限循环

    REFERENCE

    错误组合的递归 CTE 可能会导致无限循环。为了 例如,如果递归成员查询定义返回相同的 父列和子列的值,无限循环是 创建的。为防止无限循环,您可以限制 通过使用 MAXRECURSION 提示和 OPTION 中介于 0 和 32,767 之间的值 INSERT、UPDATE、DELETE 或 SELECT 语句的子句。这让 您控制语句的执行,直到您解析代码 创建循环的问题。服务器范围的默认值为 100。 指定 0 时,不应用限制。只有一个 MAXRECURSION 值 可以按语句指定

    【讨论】:

    • 一个小问题:我想在查询的开头声明 maxrecursion 参数以获得正确的注释。 declare @max_recursion int = 1000 ... option (maxrecursion @max_recursion) 我收到错误“'@max_recursion' 附近的语法不正确”。这意味着我不能将变量传递给“option()”语法?
    • 你必须为此@AlexandrKapshuk Here is a question that asked this very question创建一个动态SQL字符串
    猜你喜欢
    • 2020-11-25
    • 1970-01-01
    • 2016-12-10
    • 2017-11-05
    • 2013-11-30
    • 2020-12-13
    • 2013-03-03
    • 2016-07-09
    • 2015-08-14
    相关资源
    最近更新 更多