2016-11-07 36 views
0

我有我的触发器中的缺陷在哪里用软删除覆盖DELETE?

CREATE TRIGGER [CantDeleteStuff] ON [dbo].[Stuff] 
INSTEAD OF DELETE 
AS 
BEGIN 
    ROLLBACK 
    UPDATE [dbo].[Stuff] SET [Deleted]=1 FROM DELETED WHERE [dbo].[Stuff].[Id] = DELETED.[Id] 
END 
GO 

创建一个触发器,我认为它的意图十分明显。但是当我尝试删除一行时,出现错误

事务在触发器中结束。该批次已被中止。

如何修复?

+0

只要删除回滚语句,你应该没问题。请记住,您将不会触发删除的INSTEAD。这意味着不会发生删除事件。 –

回答

2

而不是删除将取代与您的触发代码的删除。

根据Technet的说法,触发器的回滚是问题所在。你可以在这里阅读更多。

触发器的操作就好像执行触发器时有效的未完成事务一样。无论触发触发器的语句是隐式事务还是显式事务,都是如此。

当语句开始在自动提交模式下执行时,有一个隐含的BEGIN TRANSACTION允许恢复由语句生成的所有修改,如果遇到错误。此隐含事务对批处理中的其他语句没有影响,因为它在语句完成时提交或回滚。但是,当触发器被调用时,该隐含事务仍然有效。

当触发器执行时,隐式事务开始。如果触发器完成执行并且@@ TRANCOUNT = 0,则会发生错误3609,并终止批处理。如果在触发器中发出BEGIN TRANSACTION语句,它将创建一个嵌套事务。在这种情况下,执行COMMIT TRANSACTION语句时,该语句将只应用于嵌套事务。 在触发器中使用ROLLBACK TRANSACTION时,请注意以下行为:

在当前事务中对该点进行的所有数据修改都会回滚,包括由触发器所做的任何修改。

触发器在ROLLBACK语句后继续执行任何剩余的语句。如果任何这些语句修改数据,则修改不会回滚。

触发器中的ROLLBACK关闭并释放所有在包含触发触发器的语句的批处理中声明和打开的游标。这包括由触发触发器的批处理所调用的存储过程中声明和打开的游标。在触发触发器的批次之前在批处理中声明的游标只能关闭。但是,如果出现以下情况,STATIC或INSENSITIVE游标将保持打开状态:

CURSOR_CLOSE_ON_COMMIT已设置为OFF。 静态游标是同步游标或完全填充的异步游标。 而不是使用ROLLBACK TRANSACTION,SAVE TRANSACTION语句可用于在触发器中执行部分回滚。

https://technet.microsoft.com/en-us/library/ms187844(v=sql.105).aspx

所以只是删除回滚。