SQL - 在语句完成之前,最大递归100已用尽

时间:2017-04-18 17:28:28

标签: sql sql-server tsql common-table-expression recursive-query

当我在查询下运行时,我会收到此错误。即使我使用选项(maxrecursion 0),它也不会失败,但需要很长时间,但仍然无法看到它完成。所以我必须修复我的递归代码或需要相同而不递归。基本上有两个表,一个是员工,另一个是他们的合同。同一父母下的每个雇员都可以签订一份合同(父母可以拥有或者孩子可以拥有。但这并不重要,但他们只能拥有一份。这意味着同一家庭有一行(一份合同))。我需要获得所有合同号码,并为所有父母和孩子提供相同的列。

---------------------------- ¦ Contract ¦ ¦--------------¦------------¦ ¦ ID_CONTRACT ¦ ID_EMPLOYEE¦ ¦--------------¦------------¦ ¦ 1 ¦ 1 ¦ ¦--------------¦------------¦ ¦ 2 ¦ 4 ¦ ¦--------------¦------------¦ ¦ 3 ¦ 6 ¦ ¦--------------¦------------¦ ¦ 4 ¦ 7 ¦ ¦--------------¦------------¦ ¦ 5 ¦ 12 ¦ ¦--------------¦------------¦ ¦ 6 ¦ 11 ¦ ¦--------------¦------------¦

---------------------------- ¦ Employee ¦ ¦--------------¦------------¦ ¦ ID_EMPLOYEE ¦ ID_MANAGER ¦ ¦--------------¦------------¦ ¦ 1 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 2 ¦ 1 ¦ ¦--------------¦------------¦ ¦ 3 ¦ 1 ¦ ¦--------------¦------------¦ ¦ 4 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 5 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 6 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 7 ¦ 5 ¦ ¦--------------¦------------¦ ¦ 8 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 9 ¦ 5 ¦ ¦--------------¦------------¦ ¦ 10 ¦ 5 ¦ ¦--------------¦------------¦ ¦ 11 ¦ NULL ¦ ¦--------------¦------------¦ ¦ 12 ¦ NULL ¦ ¦--------------¦------------¦ 我的代码是:

        drop table #cnt
        select DISTINCT 
            cnt.ID_CONTRACT,
            emp.ID_EMPLOYEE,
            emp.ID_MANAGER 
        into #cnt
        from 
            contract cnt (NOLOCK)
        inner join 
            employee emp (NOLOCK) ON cnt.ID_EMPLOYEE = emp.ID_EMPLOYEE

        ;WITH contactRec AS 
            (SELECT 
                cnt.ID_CONTRACT,cnt.ID_EMPLOYEE, cnt.ID_MANAGER
             FROM  
                #cnt cnt
             UNION ALL
             SELECT 
                cnt.ID_CONTRACT,emp.ID_EMPLOYEE, emp.ID_MANAGER
             FROM  
                contactRec cnt
            Inner join employee emp  on emp.ID_MANAGER = cnt.ID_EMPLOYEE
          )
            select  
              [ID_CONTRACT]
              ID_EMPLOYEE,
              ID_MANAGER
            from contactRec 

2 个答案:

答案 0 :(得分:1)

您可以将WHERE子句添加到CTE的递归元素以强制递归停止。您可能还想添加一个" Path"字段,以便您可以识别可能导致无限递归问题的递归循环:

WITH contactRec AS 
        (SELECT 
            cnt.ID_CONTRACT,cnt.ID_EMPLOYEE, cnt.ID_MANAGER,
            1 a depth, CAST(cnt.ID_Employee + '>' cnt.ID_Manager AS VARCHAR(5000)) as path
         FROM  
            #cnt cnt
         UNION ALL
         SELECT 
            cnt.ID_CONTRACT,emp.ID_EMPLOYEE, emp.ID_MANAGER,
            depth + 1 as depth, path + '>' + emp.ID_Manager as path
         FROM  
            contactRec cnt
         Inner join employee emp  on emp.ID_MANAGER = cnt.ID_EMPLOYEE
         WHERE depth <= 20 /*end recursion at 20 cycles*/
      )
        select  
          [ID_CONTRACT]
          ID_EMPLOYEE,
          ID_MANAGER,
          depth,
          path
        from contactRec;

现在它会在20个周期内死亡,你将有一个深度和路径指示器,以帮助提供有关你为什么处于无限循环的线索。

答案 1 :(得分:0)

我无法使用您提供的架构和数据生成maxrecursion错误。但是,我注意到有一件事可能会导致您的递归问题。递归cte的一般形式是:

with cte as (

   «base case»

   UNION ALL

   «recursive query»
)
select *
from cte

(顺便说一句,你已经得到了;我只是想在我的观察中引用上述内容)。在您的基本情况下,您选择所有员工。通常做的是选择顶级或底级员工,然后当你递归时,你可以沿着层次结构向下或向上(分别)。在您的具体情况下,无论如何,从上到下都是有道理的,因为顶级员工很容易识别。具体而言,您的基本案例更改为:

SELECT   cnt.ID_CONTRACT ,
        cnt.ID_EMPLOYEE ,
        cnt.ID_MANAGER
FROM     #cnt cnt

SELECT  cnt.ID_CONTRACT ,
        cnt.ID_EMPLOYEE ,
        cnt.ID_MANAGER
FROM    #cnt cnt
WHERE   ID_MANAGER IS NULL

但即使这样也无法解释为什么你会达到递归限制。你确定你的数据是非循环的(也就是说,你没有像1→2→1那样的东西)?