我在一个表上设置了一个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
如果运行回滚命令时,它会告诉你没有开始事务。
如果我将THROW替换成一个“普通”的异常(比如SELECT 1/0),事务不会被回滚。
我已经检查了xact_abort标志,它是关闭的。
使用SQL Server 2012并通过SSMS进行测试。
感谢任何帮助。
编辑 阅读@ Dan Guzman发布的文章后,我得出以下结论/总结......
SQL Server会在触发器中自动设置XACT_ABORT ON。
我的示例(上面)并未说明我的情况-实际上,我正在使用触发器创建扩展约束。
我的用例是人为的,我试图测试同一个单元测试中的多种情况(不是真实世界的情况,也不是良好的单元测试实践)。
我处理扩展约束检查并在触发器中抛出错误是正确的,但是在没有回滚事务的情况下没有真正的情况。
对于特定情况,在触发器中将XACT_ABORT OFF设置为有用;但是,您的交易仍将受到一般批次中止错误(例如死锁)的影响。
除了历史原因外,我不同意SQL Server的处理方式;仅仅因为当前没有你想继续交易的情况,并不意味着不会出现这样的情况。 我希望能够设置SQL Server以维护事务的完整性,如果您选择的架构是在源头严格管理事务,即“只有启动事务的人才能完成它”。这是在通常的故障保护措施之外的,例如,如果由于系统故障等原因未达到代码。