当 XACT_ABORT 打开时,TRY CATCH 块有什么意义?

var*_*ble 15 sql-server t-sql transaction

XACT_ABORT_ON 的代码示例:

SET XACT_ABORT_ON;

BEGIN TRY
  BEGIN TRANSACTION
    //do multiple lines of sql here
  COMMIT TRANSACTION
END TRY

BEGIN CATCH
  IF (@@TRANCOUNT > 0) ROLLBACK;
  //may be print/log/throw error
END CATCH
Run Code Online (Sandbox Code Playgroud)

由于 XACT ABORT 为 ON,任何错误都会自动回滚事务。那么 TRY CATCH 块有什么作用呢?

Cha*_*ace 20

你是对的,没有必要捕获你不打算处理的错误。SET XACT_ABORT ON;确保在所有情况下都能回滚(除了一些非常奇怪的无法捕获错误的边缘情况,Erland Sommarskog 说这些基本上是未修复的错误)。动态 SQL 中的语法错误也不会被捕获和回滚,但这只是使用良好 IDE、正确版本控制和避免动态 SQL 的又一个充分理由。

在我看来,只有CATCH当你打算处理错误时才需要处理它们。Erland 的文章通常被误解,它们的目的是处理错误,而不仅仅是捕获和重新抛出。为了正确回滚事务始终
SET XACT_ABORT ON;是必要的。

在触发器中,您不能显式回滚。如果这样做,您将收到一个虚假错误#3609 The transaction ended in the trigger. The batch has been aborted.,并且默认情况XACT_ABORTON在触发器中。


但有时您确实想要捕获并处理 SQL 代码中的错误。为此,您必须使用,并且还必须使用如图所示的BEGIN TRY BEGIN CATCH条件。ROLLBACK

例如,您可以在这个小提琴中看到,事务外的第二个插入仍然被提交,即使XACT_ABORTwas ON,因为BEGIN CATCH已使用。


TL;博士; 如果处理错误,
您只需要使用BEGIN CATCHand 条件。如果您有显式事务,则必须始终为,无论是否有, 以确保回滚正确发生。ROLLBACK;
SET XACT_ABORTONCATCH