【问题标题】:On delete cascade for self-referencing table关于自引用表的删除级联
【发布时间】:2017-07-02 20:33:46
【问题描述】:

我有一个自引用的注释表。 我试图在删除级联上写,但它需要一些例外

在表 'Comments' 上引入 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)

无法删除有子行的行

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

【问题讨论】:

  • 如果您注意错误消息并将它们的文本复制到问题中,而不是仅仅说“它接受异常”,这将真的很有帮助"。
  • 你的触发器有一个大问题。它假设只会删除一行。您需要为此类事情使用连接。
  • @Damien_The_Unbeliever 我编辑我的问题

标签: sql sql-server tsql


【解决方案1】:

假设您保留了 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);

如果有其他(非自引用)级联外键约束,它们都必须被此触发器中的操作替换。在这种情况下,我建议引入一个表变量来保存最终将从 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 FK referenced table
    DELETE FROM OtherTable
    WHERE CommentID in (select ID from @deletions)

    --This delete comes last
    DELETE FROM Comments
    WHERE id in (select ID from @deletions);

【讨论】:

  • 一个错误:无法在表 'dbo.Comments' 上创建 INSTEAD OF DELETE 或 INSTEAD OF UPDATE TRIGGER 'T_comment_Trigger'。这是因为该表有一个 FOREIGN KEY 与级联 DELETE 或 UPDATE。 发生
  • @Mike - 您需要删除 all 级联外键并在此触发器内手动实现所有级联。 (您仍然可以使用 FK,只是不能使用级联选项)
  • 我的表有 on cascade delete 用于其他外键
  • @Mike - 是的,你必须放弃它。我添加了一个示例,说明如何在同一个触发器中手动实现级联。
  • 除了这种方式还有什么办法吗?
猜你喜欢
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多