I am providing 4 examples below. My question is - which is the appropriate template to use when dealing with try/catch and transactions.
Example 1
TSQL Try / Catch within Transaction or vice versa?
The accepted answer for the above has the following structure:
BEGIN TRY
BEGIN TRANSACTION SCHEDULEDELETE
// do something
COMMIT TRANSACTION SCHEDULEDELETE
PRINT 'Operation Successful.'
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRANSACTION SCHEDULEDELETE
PRINT 'Error detected, all changes reversed'
END
//may be print/log/throw error
END CATCH
Example 2
The structure given is:
BEGIN TRANSACTION;
BEGIN TRY
-- Generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
//may be print/log/throw error
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO
Example 3
Microsoft also recommends using XACT_ABORT.
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
//do something
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- 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;
-- Test whether the transaction is committable.
-- You may want to commit a transaction in a catch block if
-- you want to commit changes to statements that ran prior
-- to the error.
IF (XACT_STATE()) = 1
BEGIN
PRINT
N'The transaction is committable.' +
'Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
Example 4
This is what I use personally
BEGIN TRY
BEGIN TRANSACTION
//do something
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRANSACTION
END ;
//may be print/log/throw error
END CATCH
To summarize:
- Example 1 - Transaction is inside the try block
- Example 2 - Try is inside the transaction block, COMMIT is after the catch block
- Example 3 - Transaction is inside the try block with xact_abort ON functionality
- Example 4 - Transaction is inside the try block, COMMIT is inside and as the last line of the try block
Is my approach (example 4) the correct way to handle try/catch and transaction in SQL. If not, then why not and which example should I use to refactor my code from example 4?