SQL Server递归存储过程

时间:2010-12-09 08:36:17

标签: sql-server stored-procedures recursion

我正在尝试列出虚拟目录中的所有文件及其子目录。这可能是下属公司的员工,这不是文件系统。也许递归存储过程可能不是答案。

情景:

  • 目录表:DirId, ParentId
  • 文件表:FileId, DirId

ParentId是父目录,根目录有parentId = NULL ...认为它是自我解释的。

现在问题......我想要一个目录及其子目录中存在的列表文件。

对于一个目录,我将创建一个存储过程:

SELECT * FROM Files Where DirId = ????

那么我如何创建一个包含子目录的存储过程呢?目前我正在使用C#代码并循环遍历每个目录。我更喜欢使用存储过程...除非你证明我错了。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

我认为你所要求的不是实际访问文件系统,而是你的数据库中的表中有一个目录结构,在这种情况下你可以使用这样的递归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

答案 2 :(得分:-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

子目录和目录将使用此脚本列出