我有一个存储在sql表中的字符串树,这是表的定义。
CREATE TABLE [FileTree] (
[ID] INT NOT NULL,
[Name] VARCHAR (MAX) NOT NULL,
[ParentID] INT NULL,
[UserID] VARCHAR (MAX) NOT NULL
);
我有一个用于删除节点及其子节点的递归删除程序,它使用了一个游标,并且在我之前关于此事的问题上的SO用户指出语法问题后,它运行得非常好。 (Deleting Tree-Nodes in a SQL table)
CREATE PROCEDURE DeleteFile
@FileID INTEGER,
@UserID VARCHAR(MAX)
AS
BEGIN
DELETE FROM [FileTree] WHERE [ID] = @FileID AND [UserID]=@UserID;
IF EXISTS(SELECT * FROM [FileTree] WHERE [ParentID] = @FileID AND [UserID]=@UserID)
BEGIN
DECLARE FileCursor CURSOR LOCAL FOR
SELECT [ID],[UserID] FROM [FileTree] WHERE [ParentID] = @FileID AND [UserID]=@UserID;
OPEN FileCursor
FETCH NEXT FROM FileCursor INTO @FileID , @UserID
WHILE @@FETCH_STATUS =0
BEGIN
EXEC DeleteFile @FileID,@UserID;
FETCH NEXT FROM FileCursor INTO @FileID , @UserID ;
END
END
END
然而,对该问题的另一个回复建议使用公用表表达式,我用Google搜索,我认为我真的不明白CTE如何在此过程中替换光标。有什么建议 ?
答案 0 :(得分:4)
您可以使用递归CTE来获取应删除的ID的所有子项,然后在DELETE语句中使用它:
with all_ids as (
select id, ParentID
from FileTree
where id = 4 -- this is the root ID that should be deleted
union all
select c.id, c.ParentID
from FileTree c
join all_ids p on p.id = c.ParentID
)
delete from file_tree
where id in (select id from all_ids);
SQLFiddle示例:http://sqlfiddle.com/#!3/ef474f/1