【发布时间】:2015-07-28 20:02:11
【问题描述】:
我的一个表上有一个 INSERT 触发器,当它发现重复时会发出 THROW。问题是我的事务似乎在这一点上被隐式回滚 - 这是一个问题,我想控制事务何时回滚。
可以使用此脚本重新创建问题:
CREATE TABLE xTable (
id int identity not null
)
go
create trigger xTrigger on xTable after insert as
print 'inserting...';
throw 1600000, 'blah', 1
go
begin tran
insert into xTable default values
rollback tran
go
drop table xTable
如果你运行 rollback tran - 它会告诉你没有 begin tran。
如果我将 THROW 替换为“正常”异常(如 SELECT 1/0),则事务不会回滚。
我检查了 xact_abort 标志 - 它已关闭。
使用 SQL Server 2012 并通过 SSMS 进行测试
任何帮助表示赞赏,谢谢。
编辑 在阅读了@Dan Guzman 发表的文章后,我得出了以下结论/总结......
SQL Server 在触发器中自动设置 XACT_ABORT ON。
我的例子(上面)没有说明我的情况 - 实际上我正在使用触发器创建扩展约束。
我的用例是人为设计的,我试图在同一个单元测试中测试多种情况(不是真实世界的情况,也不是好的单元测试实践)。
我对扩展约束检查的处理并在触发器中抛出错误是正确的,但是没有我不想回滚事务的实际情况。
在特定情况下,在触发器内设置 XACT_ABORT OFF 会很有用;但您的事务仍会受到一般批处理中止错误(如死锁)的破坏。
抛开历史原因,我不同意 SQL Server 对此的处理;仅仅因为目前没有您想继续交易的情况,并不意味着这种情况可能不会出现。 我希望看到一个能够设置 SQL Server 来维护事务的完整性,如果您选择的体系结构是在源头严格管理事务,即“只有启动事务的人,必须完成它”。除了通常的故障保险之外,例如如果您的代码由于系统故障等原因而无法访问。
【问题讨论】:
标签: sql-server transactions throw