8

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

我想调试它,SET XACT_ABORT ON;目标是在只有一个事务失败时回滚所有内容。

但我找到了几种在 StackOverflow 上存档的方法,如下所示

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还是相反?

4

3 回答 3

3

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

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

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

于 2021-11-05T09:55:18.910 回答
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;
于 2021-11-05T10:38:43.230 回答
2

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

所有你需要的是

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

如果只有一个语句,那么您甚至不需要BEGIN TRAN;COMMIT;

于 2021-11-05T13:29:07.047 回答