如何正确使用 SET XACT_ABORT ON
How to use SET XACT_ABORT ON the right way
我们最近跳伞到一个代码非常糟糕的新 ETL 项目。
我手头有一个包含 700 行和各种更新的查询。
我想用 SET XACT_ABORT ON;
调试它,目标是在只有一个事务失败时回滚所有内容。
但我找到了几种在 Whosebug 上存档的方法,例如 :
BEGIN TRANSACTION;
BEGIN TRY
-- Multiple sql statements goes here
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
或this:
BEGIN TRY
BEGIN TRANSACTION
-- Multiple sql statements goes here
COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT(ERROR_MESSAGE())
ROLLBACK TRANSACTION
END CATCH
和none这些用途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
还是相反?
不一样。它决定何时抛出错误。
你应该总是使用SET XACT_ABORT ON
,因为它更一致;几乎总是,错误将停止执行并抛出错误。否则,一半会抛出错误,另一半会继续执行。
有一个很棒的 article about this whole subject on Erland Sommarskog's site, and if you go at this point you will see a table which describes this strange behaviour. In conclusion, I recommend the General Pattern for Error Handling,因为它有很好的文档记录,并为您提供了根据自己的文档对其进行调整的机会。
感谢@George Menoutis 提供的资源。
我post这里是我的实用解决方案:
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;
如果您有 XACT_ABORT ON
,则无需手动捕获任何错误,除非您正在记录错误。 XACT_ABORT
将导致所有错误导致事务失败并回滚。
你只需要
SET XACT_ABORT ON;
BEGIN TRAN;
--do stuff
COMMIT;
如果只有一个语句那么你甚至不需要BEGIN TRAN;
和COMMIT;
我们最近跳伞到一个代码非常糟糕的新 ETL 项目。 我手头有一个包含 700 行和各种更新的查询。
我想用 SET XACT_ABORT ON;
调试它,目标是在只有一个事务失败时回滚所有内容。
但我找到了几种在 Whosebug 上存档的方法,例如
BEGIN TRANSACTION;
BEGIN TRY
-- Multiple sql statements goes here
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
或this:
BEGIN TRY
BEGIN TRANSACTION
-- Multiple sql statements goes here
COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT(ERROR_MESSAGE())
ROLLBACK TRANSACTION
END CATCH
和none这些用途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
还是相反?
不一样。它决定何时抛出错误。
你应该总是使用SET XACT_ABORT ON
,因为它更一致;几乎总是,错误将停止执行并抛出错误。否则,一半会抛出错误,另一半会继续执行。
有一个很棒的 article about this whole subject on Erland Sommarskog's site, and if you go at this point you will see a table which describes this strange behaviour. In conclusion, I recommend the General Pattern for Error Handling,因为它有很好的文档记录,并为您提供了根据自己的文档对其进行调整的机会。
感谢@George Menoutis 提供的资源。
我post这里是我的实用解决方案:
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;
如果您有 XACT_ABORT ON
,则无需手动捕获任何错误,除非您正在记录错误。 XACT_ABORT
将导致所有错误导致事务失败并回滚。
你只需要
SET XACT_ABORT ON;
BEGIN TRAN;
--do stuff
COMMIT;
如果只有一个语句那么你甚至不需要BEGIN TRAN;
和COMMIT;