CTE Query会引发Recursion Exhausted错误

时间:2017-07-31 06:06:07

标签: sql-server common-table-expression

以下CTE查询抛出"语句终止。在语句完成之前,最大递归100已经用尽。"

WITH MyCTE
AS (
SELECT o.organizationid,
        organization AS organization 
FROM organization o
    INNER JOIN store s ON s.organizationid = o.organizationid
UNION ALL
SELECT store.storeid,
            CAST(storeNAme AS NVARCHAR(50)) AS storeNAme 
FROM store
    INNER JOIN MyCTE ON store.organizationid = MyCTE.organizationid)

    SELECT DISTINCT
            Organization
    FROM MyCTE

在union all之前和之后执行子查询时,获得了followig结果。

锚定查询: -     SELECT o.organizationid,             组织AS组织     来自组织o         INNER JOIN store s ON s.organizationid = o.organizationid 结果: -

organizationid    |organization
--------------------------------
3                 | Org1
联合全部后的

查询: -

SELECT store.storeid,                     CAST(storeNAme AS NVARCHAR(50))AS storeNAme             从商店

结果: -

StoreId           |StoreName
--------------------------------
3                 | Warehouse1

我可以知道原因吗?

3 个答案:

答案 0 :(得分:3)

在查询末尾指定maxrecursion选项:

...
from MyCTE
option (maxrecursion 0)

这允许您指定CTE在生成错误之前可以递归的频率。 Maxrecursion 0允许无限递归。

答案 1 :(得分:0)

当您运行递归查询时,您允许查询调用自身。查询返回的行数不重要,但查询调用自身的次数并不重要。因此,存在进入无限循环的风险。 SQL Server为了防止这种情况发生,有一个设置将决定允许多少递归。此设置的默认值为100 - 因此,当您的查询超过100次递归(自我调用)时,您将收到此消息。

您可以通过在查询结尾添加OPTION (MAXRECURSION nn)来覆盖此设置。当 nn 是新的最大值时。

您也可以通过将此值设置为0来完全删除保护 - 它将如下所示:OPTION (MAXRECURSION 0)但是不建议这样做,因为在运行它时会不断消耗资源。

OP询问了如何避免潜在的无限循环的建议,并为递归创建退出条件。

据我所知,您正在尝试构建数据层次结构。您可以考虑引入具有层次结构级别的附加列并在某个级别停止(我在示例中选择10):

WITH MyCTE
     AS (
     SELECT o.organizationid,
            organization AS organization,
          1 lvl
     FROM organization o
          INNER JOIN store s ON s.organizationid = o.organizationid
     UNION ALL
     SELECT store.storeid,
            CAST(storeNAme AS NVARCHAR(50)) AS storeNAme,
          lvl+1
     FROM store
          INNER JOIN MyCTE ON store.organizationid = MyCTE.organizationid
     WHERE lvl<10
)
SELECT DISTINCT
    Organization
FROM MyCTE

答案 2 :(得分:0)

我认为我们可以尝试增加最大递归深度:

设置全局cte_max_recursion_depth = 10000;

根据https://forums.mysql.com/read.php?100,681245,681245