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

时间:2016-11-07 19:01:36

标签: sql sql-server tsql database-design

我有一个用

创建的触发器
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

我觉得这很明确。但是当我尝试删除一行时,我收到了错误

  

交易在触发器中结束。批次已中止。

如何解决?

1 个答案:

答案 0 :(得分:2)

而不是删除将用您的触发代码替换删除。

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

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

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

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

回滚当前交易中对该点所做的所有数据修改,包括触发器所做的任何修改。

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

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

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

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

所以只需删除Rollback。