【问题标题】:Delete trigger not working when executed执行时删除触发器不起作用
【发布时间】:2015-06-12 00:07:36
【问题描述】:

在删除 table1 中的一行后,是否有可能从 table2(它有来自 table1 的引用)中删除? (例如:如果我从Customers中删除一个CustomerID同时删除他所下的订单(OrderID))

CREATE TRIGGER DelBilete
ON Curse 
AFTER DELETE
AS 
BEGIN
  DELETE FROM Bilete 
  WHERE IDCursa IN (SELECT IDCursa FROM Curse)
END

【问题讨论】:

  • 是的,这是可能的。但是您发布的代码没有引用虚拟删除表。
  • @SeanLange - 我不明白。你能更具体一点吗?也许是一个例子?
  • 查看您的删除语句。这将删除 Bilete 中在 Curse 中有匹配行的每一行。没有条件只删除刚刚删除的诅咒行的胆汁行。将您的子查询更改为从已删除中选择,它应该是您想要的。
  • 你的问题解决了吗?
  • @AnnL。 - 我做到了.. 谢谢

标签: sql-server triggers


【解决方案1】:

有两种方法可以做到这一点:使用级联删除(您使用外键约束设置):

ALTER TABLE [dbo].[Orders]  WITH NOCHECK ADD  CONSTRAINT    
[FK_Orders_Customer] FOREIGN KEY([customerId])
REFERENCES [dbo].[Customer] ([customerId])
ON DELETE CASCADE

... 或使用触发器,正如您所尝试的那样。 (实际上,您可以尝试类似的方法。免责声明:这是凭记忆得出的,未经测试。)

CREATE TRIGGER DelBilete
ON Curse 
AFTER DELETE
AS 
BEGIN
  DELETE FROM Bilete WHERE IDCursa IN(SELECT IDCursa FROM deleted)
END
GO

如果您只是删除主键表中存在外键的位置,您将删除所有订单(或 Bilete 包含的任何内容)!

ETA:收到外键约束错误:

删除语句与引用约束冲突 “FK_Bilete_Curse”。

如果您有外键约束,并且想要从主表 (Curse) 中删除并从相关表 (Bilete) 中删除相关记录,AFTER 触发器将无法解决这个问题,正是因为它是一个 AFTER 触发器。它发生在记录被删除之后。如果无法删除它们,则触发器不会触发。如果这些记录被其他记录引用,则无法删除。

那么你有两个选择:

  1. 上面的级联删除;

  2. INSTEAD OF trigger。 (详情请参阅here。)

在您的情况下,INSTEAD OF 触发器看起来像这样(同样,来自内存和文档,未经测试):

CREATE TRIGGER DelBilete
ON Curse 
INSTEAD OF DELETE
AS 
BEGIN
   DELETE FROM Bilete WHERE IDCursa IN(SELECT IDCursa FROM deleted)
   DELETE FROM Curse WHERE IDCursa IN (SELECT IDCursa from deleted)
END
GO

使用INSTEAD OF 触发器,当您执行代码以从Curse 中删除记录时,触发器会改为运行。它从Bilete 中删除相关记录,然后从Curse 中执行删除。

INSTEAD OF 触发器不会递归运行,因此触发器中 Curse 的 DELETE 不会强制触发器再次运行。

【讨论】:

  • AnnL - 第二种方法不起作用。同样的错误
  • 错误是什么?后来我在想,如果您实际设置了外键关系,则在 Bilete 之前从 Curse 删除可能会给您带来约束错误。此外,如果Bilete 有任何依赖项,您可能会遇到与 its 依赖项相同的问题。
  • IDCursa 也出现在表 Bilete (IDCursa) 中。 The delete statement conflicted with the reference constraint "FK_Bilete_Curse".
  • 在这种情况下,您有两个选择:您可以在FK_Bilete_Curse 上设置级联删除,或者您可以尝试INSTEAD OF trigger (technet.microsoft.com/en-us/library/…)。在INSTEAD OF 触发器中,您将执行从Bilete 删除,就像在原始触发器中一样,然后从Curse 删除,这样约束就不会触发。
  • @rrrrdc 我已经更新了我的示例以显示更多详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-20
  • 1970-01-01
  • 2016-01-16
相关资源
最近更新 更多