CTE递归无限循环

时间:2019-03-28 00:16:04

标签: sql sql-server tsql

我正在使用存储过程并在SQL Server中使用CTE,并且试图从2个表中获取一些数据,但是当执行转到CTE查询时,它会遇到无限循环,并且永远不会结束,有办法防止无限循环吗?

这是我创建的查询:

WITH tableName(Id, enddate, statusDte, closeId, shceDte, calcDte, closeEndDte, ParentId, LastClose, lasCloseDte, closeClass,addSe,twon,code)
AS
(
    SELECT 
        tba.Id,
        CASE WHEN tb.ParentId IS NOT NULL 
                THEN tb.Id
             WHEN tb.statusDte IN (1,2,3) 
                THEN  tb.calcDte ELSE tb.shceDte 
                END ForecastDueDate, 
        statusDte, closeId, shceDte, calcDte, 
        CASE WHEN tb.ParentId IS NULL 
                THEN closeEndDte ELSE NULL END, tb.ParentId, 0, 
        CASE WHEN tb.ParentId IS NOT NULL 
                THEN statusDte
             WHEN tb.statusDte = 5
             AND (tb.calcDte BETWEEN '1/1/2020 12:00:00 AM' AND '12/31/2020 11:59:59 PM' 
             OR tb.closeEndDte BETWEEN '1/1/2020 12:00:00 AM' AND '12/31/2020 11:59:59 PM') 
                THEN ams.GetPreviousNthFullAuditDate(tb.Id, tb.AuditID, 2)  ELSE a.statusDate END as lastDate,
        a.closeClass, tba.addSe,tba.town,tba.code
    FROM 
        tableA tba 
    INNER JOIN 
        tableB tb ON tb.Id = tba.Id 
    WHERE 
        statusDte NOT IN (3,4) AND tba.IsAtve = 1

    UNION ALL

    SELECT 
        Id, enddate, 
        statusDte, statusDte, shceDte, calcDte, closeEndDte, ParentId,
        0, lasCloseDte, closeClass,addSe,twon,code
    FROM 
        tableName
    WHERE 
        enddate BETWEEN enddate AND '12/31/2020 11:59:59 PM'
)
SELECT * 
FROM tableName
OPTION (maxrecursion 0)

预期结果

Id                  enddate          statusDte      closeId         shceDte                 calcDte             closeEndDte                 parentId          lastClose       lastCloseDte         closeClass  addSe                               town                      code
----------- ----------------------- ------------- ----------- ----------------------- ----------------------- ----------------------- ----------------------- ----------- ----------------------- ----------- --------------------------------- ---------------------- --------------------------------------------------
133           2011-04-04 00:00:00.000 22            14453       NULL                    2011-04-04 00:00:00.000 2099-12-31 00:00:00.000 NULL                    0           NULL                    1           4707 EXECUTIVE DRIVE  ''             SAN DIEGO               123
56           2018-12-07 13:00:00.000 22            52354       NULL                    2018-12-07 13:00:00.000 2019-12-07 00:00:00.000 NULL                    0           NULL                    1           75 STATE ST FL 24  ''                BOSTON                   345
12          2021-02-05 17:00:00.000 22            75751       NULL                    2021-02-05 17:00:00.000 NULL                    NULL                    0           NULL                    1           1450 FRAZEE RD STE 308  ''           SAN DIEGO                 678
334          2019-03-07 16:30:00.000 15            66707       2019-03-07 16:30:00.000 2019-03-23 21:00:00.000 NULL                    NULL                    0           2019-03-07 16:30:00.000 1           42690 RIO NEDO, STE E  ''            TEMECULA                 91011
33          2020-01-10 17:00:00.000 22            65568       NULL                    2020-01-10 17:00:00.000 NULL                    NULL                    0           2018-01-10 17:00:00.000 1           2518 UNICORNIO ST.  ''               CARLSBAD                  136
55          2020-04-16 20:00:00.000 22            67812       NULL                    2020-04-16 20:00:00.000 NULL                    NULL                    0           2018-04-17 20:00:00.000 1           4534 OSPREY STREET  ''               SAN DIEGO                 653
66          2020-02-21 17:00:00.000 22            75956       NULL                    2020-02-21 17:00:00.000 NULL                    NULL                    0           2019-02-21 17:00:00.000 1           3511 CAMINO DEL RIO S, STE 305  ''   SAN DIEGO                 0484
094          2021-02-20 21:00:00.000 22            75629       NULL                    2021-02-20 21:00:00.000 NULL                    NULL                    0           NULL                    1           29349 EAGLE DR  ''                   MURRIETA                 345

2 个答案:

答案 0 :(得分:1)

首先,让我们尝试添加一些最佳实践。使用适当的表别名限定所有列。仅执行其中一些操作就会前后不一致,并且样式不一致很难阅读并且容易出错。

接下来,您(希望)简化了您的实际查询。诸如“ tableA”之类的通用名称妨碍理解。

下一步-您的第一种情况表达似乎非常可疑。您有一个分支返回tb.id,其他分支返回似乎是日期(或日期时间)的东西。不幸的是,您可以将int转换为日期时间。可能没有任何意义,也不会产生错误。所以-这有意义吗?

下一步-您在日期时间边界上犯了一个常见错误。根据您的数据,您可能永远不会知道这一点。但是没有理由期望这样做,并且有充分的理由编写您的逻辑以免发生任何可能性。 Tibor详细讨论了here。较短的版本-您的上限应始终是唯一的,以支持数据类型的所有可能的时间值。 23:59:59将忽略任何非零毫秒的时间值。并使用不依赖于语言或连接设置的文字格式。

接下来,您添加混乱。您在cte声明中为列命名,但是您的代码还包含一些(但不是全部-请参阅一致性注释)列的别名,这些别名与cte的实际列名有很大不同。 cte的第二列是“ enddate”,锚查询使用别名“ ForecastDueDate”

接下来,您具有:tb.statusDte = 5。字面意思是不同的东西。您还有其他以“ Dte”结尾的列,这些列显然是日期,但是不是吗?危险,危险!

接下来,您引用列“ a.closeClass”和“ a.statusDate”。没有名为“ a”的表或别名。

最后,您有:

WHERE enddate BETWEEN enddate AND '12/31/2020 11:59:59 PM'

考虑一下您写的内容。结束日期是否不总是介于结束日期和2010年12月31日之间(只要结束日期<=该值)?我认为这是您问题的根源。您不需要计算或调整锚点的内容,因此递归部分只是不断地进行选择和选择。没有结束递归的逻辑。

下一个问题显然是“现在要解决”。如果不知道您的模式,它代表什么以及您的目标,这是无法说的。在这里使用递归并不明显。

答案 1 :(得分:0)

如果数据处于记录之间的层次结构为循环的结构中,则递归进行到无限会导致SQL问题。您将看到SQL进程使用的资源正在急剧增加。 如果您使用的MAXRECURSION的值不同于0(零,则SQL可以无限制地继续递归),您将能够限制递归。 对于循环或相互引用的数据,您可以使用此MAXRECURSION参数