Previous | Table of Contents | Next |
There are several approaches to solving this problem. Ill present one approach here, but as long as you follow three basic principles of procedure transaction coding, you can use whatever method you prefer:
My preferred approach requires changes to both the procedure and the batch that executes it. In the procedure, use a transaction savepoint to mark the beginning of the work. If there is an error, roll back to the savepoint (which has no effect on @@trancount ) and use COMMIT TRAN (to restore the nesting level after the BEGIN TRAN executed earlier in the procedure). Return a non-zero status to warn the batch that the procedure failed.
create procedure order_ins_rev -- a procedure to insert orders (@item_no int, @qty int) as declare @in_stock int begin tran save tran start_work -- mark a savepoint update inventory -- deplete inventory first set @in_stock = stock_qty = stock_qty - @qty where item_no = @item_no if @in_stock < 0 -- check stock now begin rollback tran start_work -- rollback to the savepoint commit tran -- restore @@trancount raiserror (insufficient stock, 16, 1) return 99 -- warn of an error in the proc end -- add the order insert orders ( item_no, qty) values (@item_no, @qty) commit tran -- commit the transaction return 0
The batch uses the procedure return status to determine whether to continue processing. Heres the complete execution batch, with proper error handling added.
declare @ret int begin tran execute @ret = order_ins_rev 1, 6 if @ret <> 0 -- error check begin print order 1 failed quitting rollback tran return end execute @ret = order_ins_rev 2, 4 if @ret <> 0 -- error check begin print order 2 failed quitting rollback tran return end print order complete commit tran select * from inventory select * from orders
If processing fails, you can perform the actual ROLLBACK TRAN in the batch itself, where you are in control of the complete processing context.
Do......Dont
|
Procedures that modify data need to check the value of @@error after data modification statements in case a trappable error occurred during execution. This is particularly important when you are using transaction control statements.
Unfortunately, checking @@error is not sufficient protection from all errors. Some errors have the effect of immediately ending stored procedure execution and returning a negative (system-reserved) return status value to the calling procedure or batch. Other errors end both the procedure where the error was encountered and the procedure or batch that invoked it.
Previous | Table of Contents | Next |