0

當我在查詢下運行時,我收到此錯誤。即使我使用選項(maxrecursion 0),它不會失敗,但花了很長時間,仍然看不到它完成。所以我必須修復我的遞歸代碼或需要相同的遞歸。基本上有兩張桌子,一張是僱員,另一張是他們的合同。在同一家長下的每個員工可以有一份合同(父母可以有孩子可以有,但這並不重要,但他們只能有一個。這意味着同一家庭有一行(一份合同))。我需要獲得所有合同號碼,併爲所有父母和子女提供相同的專欄。SQL - 語句完成前最大遞歸100已用盡

---------------------------- ¦ 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 
+0

IS'cntrementRec'是一個錯字還是這個其他表嗎? – JNevill

+0

@JNevill,謝謝你的警告。這是錯字。我編輯過。 –

回答

1

您可以添加一個WHERE子句的CTE的遞歸元素,迫使遞歸停止。您可能還需要添加一個「路徑」字段,以便您可以識別遞歸循環,可導致無限遞歸問題:

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次死亡,你將有一個深度和路徑指示,以幫助給關於你爲什麼處於無限循環的線索。

+0

其實我沒有很多親子關卡。我有最多3個層次。但爲什麼我必須在一定的週期內死亡?有任何其他方式來解決這個問題,或者總是不得不放置where子句來阻止它。 BTW代碼工作正常,我測試了幾行,但我需要測試更多的明天,並會接受它作爲答案,如果無法找到任何錯誤。非常感謝。 –

+0

遞歸會自行停止,但您可能會遇到類似如下情況:employeeA向employeeB報告,employeeC報告給employeeA,後者向employeeA報告......並且無限循環。我發佈的代碼將幫助您確定您的層次結構的哪一段導致了無限循環。我不能徹底解決問題,因爲問題很可能出現在您的數據中。上面的代碼爲您提供了查找它的工具,以便您可以修復數據或添加代碼以防止它發生。 – JNevill

+0

我發現我也不得不在CTE的遞歸部分使用CAST(... AS VARCHAR(5000))AS Path –

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的東西)?

+0

這很好,但在我的邏輯中它不會工作,因爲可以與任何員工的水平和所有家庭只有1份合同。如果我使用WHERE ID_MANAGER IS NULL,我可能找不到與管理器沒有關聯的合同。但我可以使用兩個遞歸的一個是上升水平,一個是下降。 –

+0

也許吧。你想要回答什麼*語義*查詢?現在,您正在詢問代碼問題,但是編寫的代碼可能無法回答您打算的問題...... –

+0

@JNevill asnwer現在爲我工作。但仍無法確認所有數據。 –