如何正确使用SET XACT_ABORT ON

问题描述 投票:0回答:3

我们最近被空投到一个新的 ETL 项目,该项目的代码非常糟糕。 我手中有一个包含 700 行和各种更新的查询。

我想用

SET XACT_ABORT ON;
进行调试,目标是如果只有一个事务失败则回滚所有内容。

但我找到了几种将其存档在 StackOverflow 上的方法,例如 this:

BEGIN TRANSACTION;
BEGIN TRY

-- Multiple sql statements goes here

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

这个

BEGIN TRY
BEGIN TRANSACTION

-- Multiple sql statements goes here

COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT(ERROR_MESSAGE())
ROLLBACK TRANSACTION
END CATCH

这些都没有用途

SET XACT_ABORT ON;

我不明白,

SET XACT_ABORT ON
和使用
BEGIN TRY BEGIN TRANSACTION
一样吗?

我可以只使用:

SET XACT_ABORT ON;

-- Multiple sql statements goes here

并摆脱所有:

BEGIN TRANSACTION;
BEGIN TRY

还有,我应该先使用

BEGIN TRANSACTION
,然后使用
BEGIN TRY
,还是反过来?

sql-server t-sql try-catch rollback xact-abort
3个回答
6
投票

不一样。它决定何时抛出错误。

您应该始终使用

SET XACT_ABORT ON
,因为它更加一致;几乎总是,错误会停止执行并抛出错误。否则,一半的事情会抛出错误,另一半则继续执行。

Erland Sommarskog 的网站上有一篇关于整个主题的很棒的文章,如果您访问这一点,您将看到一个描述这种奇怪行为的表格。总之,我推荐错误处理的通用模式,因为它有很好的文档记录,并且为您提供了根据其自己的文档进行调整的机会。


3
投票

如果您有

XACT_ABORT ON
,则无需手动捕获任何错误,除非您正在进行错误日志记录。
XACT_ABORT
将导致所有错误导致事务失败并将其回滚。

您所需要的只是

SET XACT_ABORT ON;
BEGIN TRAN;
--do stuff
COMMIT;

如果只有一项陈述,那么你甚至不需要

BEGIN TRAN;
COMMIT;


2
投票

感谢您提供资源@George Menoutis。

我在这里发布我的实用解决方案:

SET XACT_ABORT ON;
BEGIN TRY
      BEGIN TRANSACTION;


      -- Multiple sql statements goes here


      COMMIT TRANSACTION;
END TRY
BEGIN CATCH
      IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
      THROW;
END CATCH;
GO

SET XACT_ABORT OFF;
© www.soinside.com 2019 - 2024. All rights reserved.