递归查询-使用T-SQL更新递归文件夹结构名称

问题描述 投票:0回答:2

我有一个表,用于存储文件共享程序的文件。表“ FileSystem”存储文件和文件夹结构。 FileSystem表具有一个“ IsFolder”字段,用于指示这是文件还是文件夹。 “ ParentId”代表文件或文件夹的父文件夹。例如:

Id  ParentId    Name        RelativePath    IsFolder
----------------------------------------------------
1   NULL        \           \               1
2   1           Test        \Test           1
3   2           Folder1     \Test\Folder1   1
4   2           myFile.txt  \Test\Folder1   0

如果将“ Test”文件夹的名称更新为“ Test2”,我想更新所有适用文件夹的RelativePath文本。

Id  ParentId    Name        RelativePath    IsFolder
----------------------------------------------------
1   NULL        \           \               1
2   1           Test2       \Test2          1
3   2           Folder1     \Test2\Folder1  1
4   2           myFile.txt  \Test2\Folder1  0

我已经尝试过使用CTE,但性能确实很慢。我完全有可能使用错误的TSQL!

CREATE TABLE [dbo].[FileSystem]
(
    [FileSystemId] [INT] IDENTITY(1,1) NOT NULL,
    [Name] [VARCHAR](500) NULL,
    [RelativePath] [VARCHAR](1000) NULL,
    [IsFolder] [BIT] NOT NULL,
    [ParentId] [INT] NULL,
    [LastWriteTime] [DATETIME] NULL,
    [FileData] [VARBINARY](MAX) NULL,
    [UploadedBy] [VARCHAR](50) NULL,
    [IsDeleted] [BIT] NOT NULL,
    [DeletedTime] [DATETIME] NULL,
    [DeletedBy] [VARCHAR](50) NULL,
    [DocumentType] [VARCHAR](10) NULL,

    CONSTRAINT [PK_FileSystem] 
        PRIMARY KEY CLUSTERED ([FileSystemId] ASC)
                    WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[FileSystem] 
    ADD CONSTRAINT [DF_FileSystem_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO

ALTER TABLE [dbo].[FileSystem] WITH CHECK 
    ADD CONSTRAINT [FK_FileSystem_FileSystem] 
        FOREIGN KEY([ParentId]) REFERENCES [dbo].[FileSystem] ([FileSystemId])
GO

ALTER TABLE [dbo].[FileSystem] CHECK CONSTRAINT [FK_FileSystem_FileSystem]

这是我尝试过的CTE,但需要20秒才能运行。

WITH CTE AS
(
    SELECT
        t.FileSystemId,
        t.ParentId,
        t.Name as RootPath,
        t.RelativePath,
        t.IsFolder
    FROM
        FileSystem AS t
    WHERE  ParentId is null
    UNION ALL
    SELECT
        t.FileSystemId,
        t.ParentId,
        CAST(REPLACE(CTE.RootPath+'\'+t.Name,'\\','\')AS VARCHAR(500)) AS RootPath,          
        t.RelativePath, 
        t.IsFolder
    FROM
        FileSystem AS t
        JOIN CTE
            ON CTE.FileSystemId=t.parentId
    WHERE
        t.IsFolder=1 AND t.FileSystemId IS NOT NULL
)
SELECT 
    CTE.RootPath,  CTE.RelativePath, CTE.FileSystemId
FROM
    CTE
WHERE
   CTE.ParentId IS NOT NULL
sql-server tsql
2个回答
0
投票

如果不重复层次结构中的路径,则不需要递归查询,因为relativepath具有所需的信息:

update filesystem
    set relativepath = (case when relativepath like '%\Test\%'
                             then replace(relativepath, '\Test\', '\Test2\'
                             else concat(left(relativepath, len(relativepath) - len('Test')),
                                         'Test2'
                                        )
                        end)
    where concat('%\', relativepath, '\%') like '%\Test\%';

0
投票

超级菜鸟错误,但我没有意识到我的ParentId上没有索引。如果CTE对任何人都有帮助,我将保留问题。

© www.soinside.com 2019 - 2024. All rights reserved.