Here is the script with the unnecessary parts striped out
USE databaseName
BEGIN TRY
DECLARE @count INT
DECLARE @ErrorMsg VARCHAR(MAX)
SET @count=(SELECT COUNT(*)
FROM xxxtable
WHERE xxxcolumn = 'xxx')
IF( @count = 0 ) --This means that the script has not been run yet
BEGIN
BEGIN TRANSACTION
--do work in here
COMMIT TRANSACTION
END
ELSE
BEGIN
SELECT 'This script has already been run before. Cannot run it again.'
END
END TRY
BEGIN CATCH
IF( Xact_state() <> 0 )
BEGIN
ROLLBACK TRAN
PRINT( 'ROLLED BACK TRANSACTION' )
SELECT Error_number() AS error_number,
Error_line() AS error_line,
Error_message() AS error_message
END
END CATCH
When the script fails, it enters the catch block and prints ROLLED BACK TRANSACTION and also displays the select statement results (error message etc).
But when I check in the database, the data until the point of failure is committed. What am I doing wrong here?
Update: After rolling back the data, the latest identity value available changes. (Suppose the highest identity available is 10, if I insert and rollback, the highest identity available is 11 and not 10 anymore). So the roll back is does not return the database to the state before the transaction. This is what was causing the problems.
Based on your update re: IDENTITY value, this is expected behaviour. A rollback will not reset the IDENTITY value back, so it will generate gaps in your ID values.
Presumably that’s what you mean when you say “the data until the point of failure is committed” – and not that all the data you’ve updated/inserted in the transaction is still there after the supposed rollback.