T-SQL:超过最大递归深度的简单递归

时间:2018-06-18 16:41:46

标签: sql-server recursion exceed

我有表格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次迭代的阈值是否过低?

谢谢!

2 个答案:

答案 0 :(得分:1)

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

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

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

注意,选项(maxrecursion 0)与unlimited ...相同,并且可能导致infinte循环

<强> REFERENCE

  

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

答案 1 :(得分:1)

如果您希望在查询开始时声明maxrecursion参数。 您可以尝试构建类似以下内容的查询:

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

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

并使用Exec执行它

您可以在此处参考以下答案:Maxrecursion parameter