2010-12-09 5 views
2

가상 디렉터리와 하위 디렉터리의 모든 파일을 나열하려고합니다. 부하 직원이있는 직원 일 수 있습니다. 파일 시스템이 아닙니다. 어쩌면 재귀 저장 프로 시저가 대답이 아닐 수도 있습니다.SQL Server 재귀 저장 프로 시저

시나리오 :

  • 디렉토리 테이블 : DirId, ParentId
  • 파일 테이블 : FileId, DirId

ParentId 상위 디렉토리와 루트 디렉토리 parentId = NULL을 가지고는 ... 그것은 자기 설명 생각합니다.

이제 문제는 ... 디렉토리와 하위 디렉토리에있는 목록 파일을 원합니다. 내가 저장 프로 시저를 작성하는 것과 하나의 디렉토리를 들어

:

SELECT * FROM Files Where DirId = ???? 

그래서 하위 디렉토리를 포함하는 저장 프로 시저를 만들 얼마나? 지금은 C# 코드를 사용하고 각 디렉토리를 반복합니다. 저장 프로 시저를 사용하는 것을 선호합니다 ... 제가 틀렸다는 것을 증명하지 않는 한.

+2

같은 [재귀 CTE 쿼리]를 고려하여 (http://msdn.microsoft.com/en-us/library/ms186243.aspx) 아마도. –

+1

SQL Server를 통해 파일 시스템에 액세스 하시겠습니까 ??? 이것은 훨씬 쉽고 응용 프로그램 코드를 통해 더 잘 수행됩니다. SQL에서 그렇게함으로써 어떤 문제가 해결되는지 설명해 주시겠습니까? – Oded

+0

왜 C#과 같은 코드에서 수행하는 것이 더 적합한 작업에 저장 프로 시저를 사용 하시겠습니까? –

답변

4

CTE을 사용해보십시오.

뭔가

DECLARE @Directory Table(
    DirId INT, 
    ParentId INT 
) 
DECLARE @Files Table(
    FileId INT, 
    DirId INT 
) 

INSERT INTO @Directory SELECT 1, NULL 
INSERT INTO @Directory SELECT 2, 1 
INSERT INTO @Directory SELECT 3, 1 
INSERT INTO @Directory SELECT 4, 2 

INSERT INTO @Files SELECT 1, 1 
INSERT INTO @Files SELECT 2, 1 
INSERT INTO @Files SELECT 3, 2 
INSERT INTO @Files SELECT 4, 2 
INSERT INTO @Files SELECT 5, 3 
INSERT INTO @Files SELECT 6, 3 
INSERT INTO @Files SELECT 7, 4 
INSERT INTO @Files SELECT 8, 4 

;WITH Directories AS (
     SELECT DirId, 
       ParentID 
     FROM @Directory 
     WHERE DirId = 2 
     UNION ALL 
     SELECT d.DirId, 
       d.ParentID 
     FROM @Directory d INNER JOIN 
       Directories p ON d.ParentId = p.DirId 
) 
SELECT * 
FROM Directories d INNER JOIN 
     @Files f ON d.DirId = f.DirId 
+0

화려한 감사합니다. 그러나 @maycil이 언급 한대로 DBA와 이에 대한 응답은 무엇입니까? – Rob

+0

나는 @maycil와 aggree하지 않는다. 재귀는 루프가없는 한 괜찮습니다. 나는 DB Doe Sseem에서 자신 만의 디렉토리 구조를 만드는 것이 바람직하지 않지만, 이것은 당신의 목표가 무엇인지에 달려있다. –

+0

@astander - 어떤 파일을 업로드하고 다운로드했는지에 대한 로그를 유지해야하므로 실제 파일 구조와 일치하는 모든 파일의 데이터베이스 항목을 추적합니다. 당신은이 과정에 대해 의문의 여지가 있지만 좋은 이유가 있습니다. – Rob

-1

실제로 재귀는 좋은 해결책이 아닙니다. DBA는

당신은 디렉토리 및 하위 디렉토리

Select d.FileName, f.* from Files f 
left Join Files fsub on fsub.DirId = f.DirId 
inner Join Directory d on d.DirId = f.DirId 

하위 디렉토리를 얻기 위해이 스크립트를 사용할 수 있으며 디렉토리이 스크립트를 나열합니다

+2

재귀가 좋은 해결책이 아닌 이유는 무엇입니까?귀하의 답변은 OP가 요구하는 것을주지 않습니다 – AdaTheDev

+0

DBA에 관한 좋은 지적입니다. CTE, – Rob

+0

@ AdaTheDev 7과 관련된 문제를 조사하고 있습니다. 성능 때문에 생각합니다. 행 레코드에서 루핑하면 CPU 사용률이 높아집니다. – maycil

1

내가 생각하기에, 우리가 재귀 사용하지 않으려는 무엇 다시 묻는 것은 실제로 파일 시스템에 액세스하는 것이 아니라 DB의 테이블에 표현 된 디렉토리 구조를 가지므로 다음과 같은 재귀 CTE를 사용할 수 있습니다.

DECLARE @DirId INTEGER 
SET @DirId = 1 

;WITH CTEFolders AS 
(
SELECT FileId, DirId FROM Files WHERE DirId = @DirId 
UNION ALL 
SELECT fi.FileId, fi.DirId 
FROM CTEFolders c 
    JOIN Folders fo ON c.DirId = fo.ParentId = c.DirId 
    JOIN Files fi ON fo.DirId = fi.DirId 
) 
SELECT * FROM CTEFolders 

여기에 좋은 소식이 있습니다. MSDN reference on recursive CTEs

+0

파일 시스템에 대한 올바른 .. apolgies. 나는 메인 섹션을 다시 썼다. – Rob