gpt4 book ai didi

sql-server - SQL Server 在使用 THROW 时回滚我的事务

转载 作者:行者123 更新时间:2023-12-02 20:17:08 24 4
gpt4 key购买 nike

我的一个表上有一个 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 来维护事务的完整性。除了通常的故障保险之外,例如如果由于系统故障等原因永远无法访问您的代码。

最佳答案

THROW 将在超出 TRY/CATCH 范围 ( https://msdn.microsoft.com/en-us/library/ee677615.aspx ) 时终止批处理。这里的含义是不会对批处理进行进一步的处理,包括插入后面的语句。您需要用 TRY/CATCH 包围 INSERT 或使用 RAISERROR 而不是 THROW

T-SQL 错误处理是一个相当大且复杂的主题。我建议您仔细阅读 Erland Sommarskog 的错误处理系列文章:http://www.sommarskog.se/error_handling/Part1.html 。这里最相关的是主题我可以防止触发器回滚事务吗? http://www.sommarskog.se/error_handling/Part3.html#Triggers 。从最佳实践的角度来看,如果您在触发器中强制执行业务规则而不进行回滚,那么触发器就不是正确的解决方案。

关于sql-server - SQL Server 在使用 THROW 时回滚我的事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30284181/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com