2013-04-18 2 views
3

데이터의 무한 루프를 처리TSQL : 나는이 테이블 FolderXDoc이

fldid|Xorder|docid 
1|1|2 
2|1|3 
3|1|4 
4|1|2 

그래서 폴더 1에 포함 된 폴더 2에는 폴더 3이 포함되어 있습니다. 폴더 3에는 폴더 4가 포함되어 있습니다. 폴더 4에는 폴더 2가 포함되어 있으므로주기가 있습니다 (1/2/3/4/2/3/4/2/3/4/ ...)

이제 폴더의 모든 요소를 ​​검색하고 싶습니다. 재귀 적으로. CTE를 사용하여이 작업을 시도했지만 데이터 순환으로 인해 작동하지 않습니다. 루프가 감지되면 재귀를 중지하고 싶습니다. 그래서 1의 포함 된 요소를 검색 할 때 결과 집합 (2,3,4)을 기대합니다.

I는 사용자 정의 기능이 시도 :주기가 포함 된 요소 발생시

CREATE FUNCTION [dbo].[DocChildren](@fldid int) 
RETURNS TABLE 
AS 
RETURN 
(
    WITH n AS 
      (SELECT f.fldid, f.docid 
      FROM folderxdoc f where f.fldid = @fldid 
      UNION ALL 

      SELECT n.fldid, nplus1.docid 
      FROM folderxdoc as nplus1, n 
       WHERE n.docid = nplus1.fldid and n.docid != @fldid) 

    SELECT docid FROM n 
) 

함수가 시작 ID 환상 루프 처리 아니지만. 이 문제를 해결하려면 어떻게해야합니까?

도움 주셔서 감사합니다.

+2

? 첫 번째 체인 전체를 표시 하시겠습니까? 위의 예에서 1/2/3/4, 1/2/3/4/2/3/4 또는 다른 것을 원하십니까? –

+3

루프 발견의 예는 CTE [here] (http://stackoverflow.com/questions/15080922/infinite-loop-cte-with-option-maxrecursion-0/15081353#15081353)에서 찾을 수 있습니다. 재귀 중에 중복 경로를 테스트하고 중복 항목을 테스트합니다. – HABO

+0

@ 등록 사용자 : 의견에 감사드립니다. 나는 그 질문을 편집했다. 내 예상 결과 세트는 1에 포함 된 모든 요소에 대해 (2,3,4)입니다. – carlptr

답변

1

@HaBo의 힌트를 사용하여 문제를 해결했습니다.

재귀 중에 경로를 조합하고 중복 항목을 확인했습니다. 현재 결과 쿼리를 찾을 수 있습니다 http://sqlfiddle.com/#!3/cc8b3/1

WITH n AS 
     (SELECT f.fldid, f.docid, ',' + cast(f.fldid as varchar(max)) + ',' levels 
     FROM folderxdoc f where f.fldid = 1 
     UNION ALL 

     SELECT n.fldid, nplus1.docid,n.levels+ cast(n.docid as varchar(max)) + ',' levels 
     FROM folderxdoc as nplus1, n 
      WHERE n.docid = nplus1.fldid AND 
      n.levels not like ('%,' + cast(nplus1.docid as varchar(max)) + ',%') 
     ) 

SELECT fldid, docid, levels FROM n 
당신이이 무한 루프 중 하나에 실행할 때 당신이 원하는 것이 무엇 출력
1

아마도 노드가 방문되었을 때 표시 할 임시 테이블이 도움이 될 수 있습니다.

기본적으로 각 노드를 방문 할 때 임시 테이블에 밀어 넣고 각 노드를 임시 테이블과 비교합니다. 기존 노드를 찾으면 중지하십시오.

그래도이 기능을 구현하려면 커서가 필요합니다.