【问题标题】:SQL Server ON DELETE TriggerSQL Server ON DELETE 触发器
【发布时间】:2012-04-17 07:21:27
【问题描述】:

我正在尝试创建一个基本的数据库触发器,当删除 database2.table2 中的一行时,该触发器有条件地从 database1.table1 中删除行。我是触发器的新手,并希望学习完成此任务的最佳方法。这是我到目前为止所拥有的。有什么建议吗?

CREATE TRIGGER sampleTrigger
    ON database1.dbo.table1
    FOR DELETE
AS
    IF EXISTS (SELECT foo
               FROM database2.dbo.table2
               WHERE id = deleted.id
               AND bar = 4)

-- If there is a row that exists in database2.dbo.table2 
-- matching the id of the deleted row and bar=4, delete 
-- it as well.

-- DELETE STATEMENT?

GO

【问题讨论】:

  • 您需要考虑到触发器每个语句触发一次(并且许多开发人员认为NOT每行触发一次)并且Deleted 伪表可能包含多行(如果您的语句删除了多行)
  • @marc_s - 在系统中,一次只能删除一行(应用程序前端)。您能否详细说明您的意思。是不是把WHERE id = deleted.id改成WHERE id IN (SELECT id FROM deleted)这么简单?
  • @ShawnH。是的,应该就是这么简单。我认为 Marc 的意思是,如果以某种方式从某处调用了批量删除,则触发器只会为整个语句而不是每行触发一次,因此使用IN 应该以任何一种方式对其进行排序。
  • @ShawnH:是的,基本上这种改变会起作用——只是不要期望/假设Deleted 表总是只有一行——它可能有多个。因此,如果 Deleted 伪表中有多行,那么您的原始语句 ....WHERE id = deleted.id 在其他系统中将惨遭失败
  • @marc_s - 很高兴知道。未来的应用程序谢谢你们。

标签: sql-server sql-server-2005 triggers


【解决方案1】:
CREATE TRIGGER sampleTrigger
    ON database1.dbo.table1
    FOR DELETE
AS
    DELETE FROM database2.dbo.table2
    WHERE bar = 4 AND ID IN(SELECT deleted.id FROM deleted)
GO

【讨论】:

  • table1 的记录也会被删除吗?对不起,如果这听起来像一个愚蠢的问题...
  • @Matthieu yes 表 1 中的行也将被删除。在上面的示例中,这些是在表 deleted 中访问的行。
  • 谢谢@Magnus。我不确定,因为如果您使用 INSTEAD OF DELETE 而不是 FOR DELETE(感谢格式化 ;)),那么除非在触发器中明确指定,否则记录不会被删除。
  • 触发器不应该是“ON database2.dbo.table2”吗?我的意思是,OP 想要一个“...触发器,它有条件地从 database1.table1 中删除行 当删除 database2.table2 中的一行时”。
【解决方案2】:

更好用:

DELETE tbl FROM tbl INNER JOIN deleted ON tbl.key=deleted.key

【讨论】:

  • 您的意思是在AS ... 触发器主体中使用它?
【解决方案3】:

INSERTEDDELETED 是虚拟表。它们需要在FROM 子句中使用。

CREATE TRIGGER sampleTrigger
    ON database1.dbo.table1
    FOR DELETE
AS
    IF EXISTS (SELECT foo
               FROM database2.dbo.table2
               WHERE id IN (SELECT deleted.id FROM deleted)
               AND bar = 4)

【讨论】:

    【解决方案4】:

    我建议使用exists 而不是in,因为在某些情况下这意味着空值the behavior is different,所以

    CREATE TRIGGER sampleTrigger
        ON database1.dbo.table1
        FOR DELETE
    AS
        DELETE FROM database2.dbo.table2 childTable
        WHERE bar = 4 AND exists (SELECT id FROM deleted where deleted.id = childTable.id)
    GO
    

    【讨论】:

    • 根据链接的 SO 问题中的大多数答案,如果您使用 INEXISTS 并没有什么不同。数据库引擎将产生完全相同的执行计划。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多