【问题标题】:Delete trigger not being executed删除触发器未执行
【发布时间】:2012-07-17 20:02:16
【问题描述】:

我有一张桌子Absence PK AbscenceId(是的拼写错误)。我有另一个表Note,在Absence 中有一个名为AbsenceId 的FK(这次拼写正确)。 FK 约束为:

ALTER TABLE [dbo].[Note]  WITH CHECK ADD  CONSTRAINT [FK_Note_Absence] FOREIGN KEY([AbsenceId])
REFERENCES [dbo].[Absence] ([AbscenceId])
GO

Absence 被删除时,我希望所有Notes 都可以使用它。 CASCADES 无法做到这一点,因为 Note 也可以属于其他东西。

所以我创建了一个触发器来在删除缺席时删除笔记:

ALTER TRIGGER [dbo].[TR_OnAbsenceDelete] ON [dbo].[Absence]
    FOR DELETE AS

    DELETE FROM [Note]
        WHERE AbsenceId IN ( SELECT AbscenceId FROM Deleted )

但是当我删除一个附有NoteAbsence 时,我得到:

Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_Note_Absence". The conflict occurred in database "ReturnToWork", table "dbo.Note", column 'AbsenceId'.
The statement has been terminated.�

这几乎就像触发器没有被执行?

【问题讨论】:

  • 您是否尝试过使用 INSTEAD-OF 触发器?您还必须删除最初被删除的记录。如果你的 FK 已经有一个删除操作,你就不能使用它。
  • 错误信息是不言自明的,不是吗?您不能只从Note 中删除该行,还必须清理其他表中引用它的所有行。
  • 我完全理解这个错误,我想我只是假设触发器在之前而不是之后执行,并且不确定触发器是否被调用。

标签: sql sql-server triggers sql-delete


【解决方案1】:

您的触发器需要编写为 INSTEAD OF 触发器,首先从 Note 中删除,然后从 Absence 中删除。

CREATE TRIGGER [dbo].[TR_OnAbsenceDelete] ON [dbo].[Absence]
    INSTEAD OF DELETE AS
BEGIN

    DELETE FROM n
        FROM deleted d
            INNER JOIN Note n
                ON d.AbscenceId = n.AbsenceId

    DELETE FROM a
        FROM deleted d
            INNER JOIN Absence a
                ON d.AbscenceId = a.AbscenceId
END

【讨论】:

  • 如果有什么失败,我会得到一个完整的回滚吗?
  • 我编写了一个 ruby​​ 脚本来根据 FK 约束自动执行此操作。效果很好,也许其他人也会发现它有用。我发布了它here
【解决方案2】:

问题是当您尝试从缺席中删除记录时,由于引用约束而失败。如果删除成功,则将调用您的删除触发器。

也如此链接中所建议,您可以尝试使用 How can I fire a trigger BEFORE a delete in T-SQL 2005? 代替

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 2015-06-05
    相关资源
    最近更新 更多