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
XACT_STATE indicates whether the request has an active user transaction, and whether the transaction is capable of being committed.
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.
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.
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.
@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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With