![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
The insert trigger fires. At the first statement of the insert trigger's try block, @@trancount=1. Why 1? |
|
Supposedly, set xact_error on causes auto-rollbacks. Fine, but the above happens with set xact_error off (unless I am actually not setting it in the right place.) |
#3
| ||||
| ||||
|
|
Gene Wirchenko (genew (AT) ocis (DOT) net) writes: The insert trigger fires. At the first statement of the insert trigger's try block, @@trancount=1. Why 1? When you are in a trigger, you are always in a transaction. If you did not start one explicitly, there is still an implicit one defined by the statement that fired the trigger. This is an essential point: the trigger is part of the INSERT statemnet, and if the trigger fails, the INSERT statement should also be rolled back. |
|
Supposedly, set xact_error on causes auto-rollbacks. Fine, but the above happens with set xact_error off (unless I am actually not setting it in the right place.) When you are in a trigger XACT_ABORT is ON by default. Furthermore, if you roll back the transaction in the trigger, the batch is aborted. |
|
Error handling in SQL Server is a patchwork of inconsistencies. A lot |
|
inherited from Sybase, but Microsoft has been careful to add their own madness. Up to SQL 2000, an error in a trigger always aborted the batch, but starting with SQL 2005 you can prevent that with an explicit SET XACT_ABORT OFF in the trigger. |
#4
| ||||||
| ||||||
|
|
Had I not been checking trigger code, there would not have been an implicit transaction created, and it would have been correct (and a good idea) to have a BEGIN TRANSACTION. Since the code in question is a trigger, there is no need for a BEGIN TRANSACTION, but it does not hurt. |
|
In the trigger, because a raiserror() caused the catch block to be executed, a rollback will automatically occur. |
|
Were it not trigger code, then the setting of SET XACT_ABORT would matter. |
|
Does the setting for SET XACT_ABORT get restored when a trigger finishes execution? |
|
How does this work when there are other procedures called? Same question, but is it any different if the lower-level procedure raises an error (as does your error handler)? |
|
Nothing that I have read has mentioned when to set SET XACT_ABORT. Is any time before an error occurs acceptable? From your last paragraph, the answer to this appears to be yes. Correct? |
#5
| |||
| |||
|
|
Gene Wirchenko (genew (AT) ocis (DOT) net) writes: |
|
This is getting confusing even for me! You see, normally RAISERROR does not terminate the batch, even if XACT_ABORT is on. But yes, in a trigger. This is probably for compatibility reasons. |
#6
| |||
| |||
|
|
It does not say why it normally does. I think the reason is that a raiserror() with a severity >=11 triggers the catch block, but it is not documented (that I can see). |
#7
| |||
| |||
|
|
Gene Wirchenko (genew (AT) ocis (DOT) net) writes: It does not say why it normally does. I think the reason is that a raiserror() with a severity >=11 triggers the catch block, but it is not documented (that I can see). RAISERROR should invokes the CATCH block, so much is right. This is applies to both triggers and regular code. |
|
As for what is documented or not is this madhouse I don't know. I only know that the updated version of my article on error handling is long overdue... |
#8
| |||
| |||
|
|
Nope. If the severity is <=10, then raiserror() will not result in the catch block triggering. This is documented. I do not know why it is this way, but it is. |
![]() |
| Thread Tools | |
| Display Modes | |
| |