--Drop Table Tab1
Begin Transaction TR1;
Save Transaction TR1;
Create Table Tab1(f1 decimal(10,0));
Begin Transaction TR2
Save Transaction TR2
insert into Tab1 values(1);
Begin Transaction TR3;
Save Transaction TR3;
insert into Tab1 values(2);
Begin Try
insert into Tab1 values('OK');
Commit Transaction TR3;
END TRY
BEGIN Catch
print 'catch'
RollBack Transaction TR3;
End Catch
insert into Tab1 values(3);
Commit Transaction TR2
insert into Tab1 values(4);
Commit Transaction TR1;
--Commit Transaction;
select * from Tab1;
Drop Table Tab1
Select @@TRANCount
Error Occures :
Msg 3931, Level 16, State 1, Line 17 The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.
How to handle this.
When certain type of errors get raised you cannot rollback to a save point. See Martin Smith's answer to Rollback transaction to savepoint on failing ALTER TABLE … ADD CONSTRAINT. The way you detect this is to test
Xact_state()
.However your problem is somewhat different because you're also trying to use nested transactions. Nested transactions don't really work in SQL as we would expect them to.
For example this fails with
Cannot roll back TR2. No transaction or savepoint of that name was found.
From Nesting Transactions
Committing inner transactions is ignored by the SQL Server Database Engine
It is not legal for the transaction_name parameter of a ROLLBACK TRANSACTION statement to refer to the inner transactions of a set of named nested transactions. transaction_name can refer only to the transaction name of the outermost transaction
Paul S. Randal explores this further in A SQL Server DBA myth a day: (26/30) nested transactions are real
The best you can do is use Save points instead and check the Xact_state in your catch and at the end.