关于自引用表的删除级联

Mik*_*ike 3 sql t-sql sql-server

我有一个自我引用的评论表.我试着写删除级联,但它需要一些例外

在表'注释'上引入FOREIGN KEY约束'FK_Comments_Comments'可能会导致循环或多个级联路径.指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束.

然后尝试编写一个触发器,但它再次出现异常

CREATE TRIGGER [dbo].[T_comment_Trigger]
    ON [dbo].[Comments]
    FOR DELETE
AS
    DELETE FROM Comments
    WHERE ParentId =(SELECT deleted.id FROM deleted)
Run Code Online (Sandbox Code Playgroud)

无法删除包含子项的行

如何为我的自引用表删除级联?

Dam*_*ver 6

假设您保持FOREIGN KEY约束,则无法在FOR DELETE触发器中修复问题.FOR触发(也称为AFTER触发器)活动发生触发.并且外键将阻止在有引用的情况下删除行.外键检查删除之前发生.

你需要的是一个INSTEAD OF触发器.您还需要记住,您当前的触发器只是试图处理一个"级别"的引用.(因此,如果第3行引用第2行,第2行引用第1行,并删除第1行,则触发器仅尝试删除第2行)

所以,像:

CREATE TRIGGER [dbo].[T_comment_Trigger]
    ON [dbo].[Comments]
    INSTEAD OF DELETE
AS
    ;WITH IDs as (
       select id from deleted
       union all
       select c.id
       from Comments c
              inner join
            IDs i
              on
                 c.ParentID = i.id
    )
    DELETE FROM Comments
    WHERE id in (select id from IDs);
Run Code Online (Sandbox Code Playgroud)

如果存在其他(非自引用)级联外键约束,则它们都必须由此触发器中的操作替换.在这种情况下,我建议引入一个表变量来保存最终将从Comments表中删除的所有ID的列表:

CREATE TRIGGER [dbo].[T_comment_Trigger]
    ON [dbo].[Comments]
    INSTEAD OF DELETE
AS
    declare @deletions table (ID varchar(7) not null);
    ;WITH IDs as (
       select id from deleted
       union all
       select c.id
       from Comments c
              inner join
            IDs i
              on
                 c.ParentID = i.id
    )
    insert into @deletions(ID)
    select ID from IDs

    DELETE FROM OtherTable
    WHERE CommentID in (select ID from @deletions)

    --This delete comes last
    DELETE FROM Comments
    WHERE id in (select ID from @deletions);
Run Code Online (Sandbox Code Playgroud)