Hello,Let's assume executed the following two prerequisite statements on an existing database:CREATE TABLE Temp( Field int not null);CREATE TRIGGER TG_Temp ON Temp INSTEAD OF INSERTASBEGIN RAISERROR(N'Insertions are not allowed.', 16, 1);ENDNow, please consider the following statements, which consist the objective of the questions and the model for some real important situations:BEGIN TRAN-- creating a savepoint:SAVE TRAN sp;BEGIN TRY -- because of the intended trigger, the following statement will raise an expected error ("Insertions are not allowed.") with a severity of 16, so the control will be passed to the CATCH block: INSERT INTO Temp (Field) VALUES (NULL);END TRYBEGIN CATCH PRINT error_message(); -- at this point the transaction has (strangely?) become doomed (uncommittable), so the following desired statement will raise a typically error ("The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.") with a severity of 16, so the execution will terminate: ROLLBACK TRAN sp;END CATCH-- this statement will never be hit:COMMIT;(#1) The primary question is why the transaction becomes doomed, because according to the official documentation (see the links bellow):"A transaction enters an uncommittable state inside a TRY block when an error occurs that would otherwise have ended the transaction."For SQL Server 2008: http://msdn.microsoft.com/en-us/library/ms179296.aspxFor SQL Server 2005: http://msdn.microsoft.com/en-us/library/ms179296%28SQL.90%29.aspxThe following simple code demonstrates that the used insert statement does not end a transaction:BEGIN TRAN;INSERT INTO Temp (Field)VALUES (NULL);-- because the transaction has not ended, 1 will be printed:PRINT @@trancount;ROLLBACK;Now, if we disable the trigger (ALTER TABLE Temp DISABLE TRIGGER TG_Temp;) and run again the statements which consist the objective of the questions, everything goes just as expected: an error occurs ("Cannot insert the value NULL into column 'Field', table 'Temp'; column does not allow nulls. INSERT fails."), the control is passed to the CATCH block, but the transaction is in a normal committable state, so the rollback to savepoint statement does not fail and the final commit statement is hit.This unexpected (or apparently non-according to the documentation) behavior has major implications, because makes in some way TRY...CATCH blocks unuseful in certain situations, as long as they can doom transactions in some strange ways.Finally, the secondary and the last question is related to the things discussed above. Let's run separately the following statements (the trigger remains disabled):-- this will cause an error with a severity of 16:INSERT INTO Temp (Field)VALUES (NULL);-- this statement will be hit:PRINT 'x';And now, run the following statements:DECLARE @var int;-- this will also cause an error with a severity of 16:SET @var = convert(int, 'x');-- this statement will never be hit:PRINT 'x';(#2) The question is why in the first situation the execution continues and opened transactions (if exist) remain intact (this is the expected behavior) and in the second situation the execution stops and opened transactions are rolled back, taking in consideration that in both cases the error's severity is 16 (determined by using TRY...CATCH blocks end error_severity() function)? Does exist any other factors (like implicit transactions for example) other than error's severity that influence the behavior or is there some official documentation that can help?Thank you very much!Sincerely,Ionuț-Gabriel NicaSoftware Developer
Version
Category
Operating System
Platform