Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server TRY...CATCH with XACT_STATE

I have a question regarding the MSDN documentation for TRY CATCH blocks. Check out this article and scroll down to Example C "Using TRY…CATCH with XACT_STATE"

http://msdn.microsoft.com/en-us/library/ms175976.aspx

The example first places a COMMIT TRANSACTION within the Try block, and then places a second one in the Catch block if XACT_STATE()=1.

However I thought a Catch block will only execute in case of an error. So how could both the Catch block execute and XACT_STATE return 1? That seems contradictory.

There is an unanswered comment within the XACT_STATE documentation which asks this same question

http://msdn.microsoft.com/en-us/library/ms189797.aspx

like image 935
ElPresidente Avatar asked Apr 16 '13 17:04

ElPresidente


People also ask

What is Xact_state ()?

XACT_STATE indicates whether the request has an active user transaction, and whether the transaction is capable of being committed.

How do I catch an error message in SQL Server?

When called in a CATCH block, ERROR_MESSAGE returns the complete text of the error message that caused the CATCH block to run. The text includes the values supplied for any substitutable parameters - for example, lengths, object names, or times. ERROR_MESSAGE returns NULL when called outside the scope of a CATCH block.

Can we use try catch in SQL Server function?

Note that you cannot use TRY... CATCH blocks inside T-SQL UDFs. If you have to capture errors that occur inside a UDF, you can do that in the calling procedure or code.

Can we use nested try catch in SQL Server?

CATCH construct to handle errors encountered by the CATCH code. Errors encountered in a CATCH block are treated like errors generated anywhere else. If the CATCH block contains a nested TRY... CATCH construct, any error in the nested TRY block will pass control to the nested CATCH block.


1 Answers

@user1181412 My analysis is as follows: This comment:

-- A FOREIGN KEY constraint exists on this table.

--This statement will generate a constraint violation error

is the answer to your question. What is happening is that when the DELETE statement executes, it generates a constraint violation error and the subsequent COMMIT does not execute. The XACT_STATE of the transaction is now 1 and the CATCH block is executing.

At the top, you have

SET XACT_ABORT ON;

This causes the transaction state to be uncommittable and hence this code block will rollback the transaction:

-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
    PRINT
        N'The transaction is in an uncommittable state.' +
        'Rolling back transaction.'
    ROLLBACK TRANSACTION;
END;

However, if you change to "SET XACT_ABORT OFF;" then the CATCH block would be hit albeit the transaction state will be "committable" as XACT_STATE = 1.

NOTE: Delete would still not be done as the constraint violation is still there, but you would see this printed:

(1 row(s) affected) The transaction is committable.Committing transaction.

like image 79
Sudhanshu Mishra Avatar answered Oct 04 '22 22:10

Sudhanshu Mishra