Author |
Topic |
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-26 : 17:14:36
|
I am calling a sp from another sp. I used the format from an example I had found here on try catch with trans statements. I tested rollback with a divide by zero in the second sp. I ran it from sql mgt studio tho it will be called from .net app. It seems to rollback everything in both sp's and I get a divide by zero error. But I also get the rollback error.Msg 3903, Level 16, State 1, Procedure uspInsert_RouteDetailToOrderDetail, Line 49The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.(1 row(s) affected)Msg 50000, Level 16, State 1, Procedure uspInsert_RouteDetailToOrderDetail, Line 83Error 50000, Level 16, State 1, Procedure uspInsert_tblOrderForRouteSales, Line 111, Message: Error 8134, Level 16, State 1, Procedure uspInsert_tblOrderForRouteSales, Line 70, Message: Divide by zero error encountered.Here is the outline of the two procedures. AFter having read other posts like this I made sure that the sp's had SET XACT_ABORT ON SET ARITHABORT ON SET NOCOUNT onThis time the message only mentioned the trans rollback. It did not specify divide by zero but it was placed in the error table I use and all was rolledbacked. thanks for any help. Don't know if I should just leave it alone?---------------------------------First spuspInsert_RouteDetailToOrderDetailBegin transaction Begin try--do and insert and update to a table and then call a stored proc Insert… Update… Exec uspInsert_tblOrderForRouteSales @rid End try Begin catch Rollback transaction--- put error info in error tab Raiseerror (@errormessage)End catchIF @@TRANCOUNT > 0 COMMIT TRANSACTIONRETURN 02nd procuspInsert_tblOrderForRouteSales (@rid int)begin transaction begin try exec usp_get_ordernumber -- this generates an usernumber that it returns insert into tblOrder….. set @OrderID = SCOPE_IDENTITY() uspinsertOrderdetail… select 1/0 --trigger rollback update tblroutes….. end trybegin catch Rollback transaction--- put error info in error tab Raiseerror (@errormessage)End catchIF @@TRANCOUNT > 0 COMMIT TRANSACTIONRETURN 0 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-07-26 : 17:31:34
|
ROLLBACK TRANSACTION statement that does not have a transaction name rolls back all nested transactions and decrements @@TRANCOUNT to 0. Ideally, you should program defensivly and check the trancount before rolling back:Begin catchIF @@TRANCOUNT > 0BEGIN Rollback transactionEND |
 |
|
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-26 : 18:00:55
|
Ok, I am confused. Because I have IF @@TRANCOUNT > 0COMMIT TRANSACTIONbut you say that I should also(?) have Begin catchIF @@TRANCOUNT > 0BEGIN Rollback transactionENDat the beginning of the catch orshould have it instead ofIF @@TRANCOUNT > 0COMMIT TRANSACTIONat the end.I guess, I am not clear on the use of @@trancount. |
 |
|
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-26 : 18:08:56
|
I have a simpler sample. when I put the select 1/0 in the first proc, I do not get the rollback error. But if I put it in the second one, I do. In both cases the procedure is rolled back. So I am confused about how to use transcount and I guess the fact that the first proc never calls the second when it rolls back, I don't get the extra transcount. But I still don't understand what I put and where I put whatever it is regarding the transcount.procedure numtestSET NOCOUNT on; SET XACT_ABORT on; SET ARITHABORT ONbegin transaction begin trydeclare @OrderNumber intexec usp_GetNewOrderNumber @OrderNumber = @OrderNumber outputEND TRYBEGIN CATCH ROLLBACK TRANSACTIONRAISERROR @ErrorMessageEND CATCHIF @@TRANCOUNT > 0 COMMIT TRANSACTIONRETURN 0 ---second procprocedure [dbo].[usp_GetNewOrderNumber] @OrderNumber int output SET NOCOUNT on; SET XACT_ABORT on; SET ARITHABORT ONbegin transaction begin try insert into [tblOrderNumber] default values set @OrderNumber = scope_identity() delete from tblOrderNumber where OrderNumberID = @OrderNumberEND TRYBEGIN CATCH ROLLBACK TRANSACTIONRAISERROR @ErrorMessageEND CATCHIF @@TRANCOUNT > 0 COMMIT TRANSACTIONselect @OrderNumberRETURN 0 |
 |
|
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-26 : 19:03:53
|
I changed the code to read:begin trans begin try exec stuffend trybegin catch if @@transcount > 0 rollback transactionend catchif @@transcount > 0 commit transactionreturn 0The second is the same:begin trans begin try insert... select 1/0end trybegin catch if @@transcount > 0 rollback transactionend catchif @@transcount > 0 commit transactionreturn 0In this case everything is rollbacked and I do not get the rollback error. Maybe this is what happens:first trans in first proc t = 1frist trans in second proc, now t = 2after the 1/0, the if @@trans > 0, rollback occurs and that decrements trans so entering first proc t = 1, then the rollback for proc 1 occurs leaving t = 0.Question: does explicitly checking the transcount decrement it? because that is the only difference I made: if @@transcount > 0, rollback --- instead of just: rollback. |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-07-26 : 19:37:21
|
quote: Originally posted by smh Ok, I am confused. Because I have IF @@TRANCOUNT > 0COMMIT TRANSACTIONbut you say that I should also(?) have Begin catchIF @@TRANCOUNT > 0BEGIN Rollback transactionENDat the beginning of the catch orshould have it instead ofIF @@TRANCOUNT > 0COMMIT TRANSACTIONat the end.I guess, I am not clear on the use of @@trancount.
Yes, both places, if you leave your code as it is. If you move the BEGIN AND COMMIT inside the TRY block, then you don't need to check the commit. |
 |
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2012-07-27 : 01:11:23
|
You have to make sure you commit or rollback all levels of nested transactions:-- loop to commit everythingwhile @@trancount > 0 commit-- loop to rollback everythingwhile @@trancount > 0 rollback CODO ERGO SUM |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-07-27 : 11:18:23
|
I would not argue against that practice, but you don't need to loop for a rollback. A single rollback rolls the entire nested chain back. |
 |
|
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-27 : 13:01:22
|
Lamphrey writes: " Yes, both places, if you leave your code as it is. If you move the BEGIN AND COMMIT inside the TRY block, then you don't need to check the commit."Do you mean putting the begin Trans within the Try/catch block rather than vice versa as I have done? I have found numerous discussions one way or another on this. Some say there are real differences others say it is a question of style. You are saying, I guess, and at least in this particular case, that this is a style issue and by using the begin trans and commit inside the try block, the only difference is not needing to check the commit?SET NOCOUNT on;SET XACT_ABORT on;SET ARITHABORT ONBEGIN TRY BEGIN TRANSACTION INSERT INTO dbo.ordertbl (ord_number, client_number) VALUES (@x, @y) INSERT INTO dbo.order_detail (ord_number) VALUES (@z) exec uspChangeCustomerID @CID COMMIT TRANSACTIONEND TRYBEGIN CATCH IF @@TRANCOUNT() > 0 ROLLBACK TRANSACTION -- error handlingEND CATCH |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-07-27 : 13:18:09
|
That's correct.If the code get's to the commit, then you want to commit it. Since it is in a try/catch block there is no need to check for other open transactions to commit. In fact, I'd argue that you don't want to check for multiple, as that "unit of execution" should be as agnositic as possible. If there is an error then the execution will transfer to the catch block where you do want to check for open transactions incase the error happened at a lower level and was already rolled back. |
 |
|
smh
Yak Posting Veteran
94 Posts |
Posted - 2012-07-27 : 19:07:46
|
Thank you for the discussion. I have confidence that rollback will occur no matter at what point the procedure is in the process of execution. I will be posting another separate question after I have worked some samples as to how to catch a concurrency violation in a procedure like the one I am doing now, where there is an update or an insert and an entire rollback occurs. Up until know I have issued a user -defined message and trapped the concurrency error, but have not done so when multiple actions where a rollback and notification of concurrency violation would have to be made. |
 |
|
|