In my code, I often use nested stored procedures. The processing of my stored procedures all perform several operations in the database, so they are encapsulated in a transaction. My stored procedures children can also be performed as a parent. I therefore start all my procedures stored as a child by a BEGIN TRAN after the BEGIN TRY and in case of error, I test the following condition before rollback: IF ##trancount = 1 and xact_state()<>0. My question is, when I perform an EXECUTE of a stored procedure, is that the value of #trancount can be changed by another EXECUTE, apart from internal or external stored procedure calls.
Example:
the stored procedure A calls the stored procedure B
the stored procedure C does not use any other stored procedure
The processing of each stored procedure is encapsulated in a transaction
Is that, in the same session the present case can occur:
I execute the stored procedure A, the value of ##trancount changes to 1 and then to 2 after the BEGIN TRAN of the stored procedure B
Now, let’s imagine that my procedure is not finished but, at the same time, the SQL Server engine executes the procedure stored C on the same session. Is the value of #trancount after the BEGIN TRAN of the stored procedure C is 1 or 3?
Related
I have a pretty big stored procedure with a lot of select/insert/delete statements. I would like all of this to be either commited or rolled back when something wrong happens during execution.
My question: is this "on" by default for a stored procedure, or do I need do add something? I've read somewhere that stored procedure commands which were already executed will not be rollback when any command after would fail. Is it true?
If this is the case putting this inside stored procedure: BEGIN TRAN and at the end COMMIT do the job?
CREATE PROCEDURE [dbo].[SP1]
#param1 INT
AS
set xact_abort on;
BEGIN TRAN;
SET NOCOUNT ON;
DECLARE X INT;
--stored procedure all business code
COMMIT TRAN;
Normal stored procedures in SQL Server are not atomic, so you need to handle be code with BEGIN TRAN/COMMIT to ensure all-or-nothing behaviour.
It is also good to wrap it with TRY/CATCH block to handle errors.
It is worth to note that natively compiled stored procedures are atomic.
Atomic Blocks in Native Procedures
Atomic blocks are executed (atomically) within the transaction. Either all statements in the block succeed or the entire block will be rolled back to the savepoint that was created at the start of the block. In addition, the session settings are fixed for the atomic block
I have a complex script that contains many stored procedures and I need to do a rollback in all cases.
BEGIN TRANSACTION;
INSERT INTO Table1 VALUES(1);
INSERT INTO Table2 VALUES(2);
EXEC storedprocedure1
EXEC storedprocedure2
....
ROLLBACK;
I have not checked all stored procedures inside (if there is or not other transaction).
I ask if there is a way to rollback the entire script (stored procedures included) independently by presence of other transaction inside the stored procedures.
Thanks!
(Assuming SQL Server)
There is no need to check inside those stored procedures.
The ROLLBACK will rollback all the way to the outer-most transaction, including rolling-back all transactions within storedprocedure1 and storedprocedure2, even if those nested transactions are committed within those procedures.
Selecting ##TRANCOUNT will show you that any ROLLBACK sets the transaction count of the session back to 0.
So if you rollback the outer transaction, anyone who may be expecting those nested transactions to commit is going to be disappointed.
If a stored procedure contains multiple statements e.g. first an insert, then an update and finally a deletes and the stored procedure gets killed in the middle of the delete, does the insert and update also have to be rolled back? Or does it only roll back the delete i.e. the implicit transaction?
As explained in Transactions, each statement will be executed as an implicit transaction. If a statement fails then the effect of prior statements will remain committed.
Note that the entire stored procedure may be executed within an explicit transaction created by the calling code.
insert and update have to be commited but delete Statement was rolled back
since you have no explicit BEGIN TRANSACTION in the stored procedure, each statement will run on its own with no ability to rollback any changes if there is an error.
However, if before you call the stored procedure you issue a BEGIN TRANSACTION, then all statements are grouped within a transaction and can either be COMMITted or ROLLBACKed following stored procedure execution.
Reference: KM.
How does SQL Server treat statements inside stored procedures with respect to transactions?
I'm using SQL Server 2014; my stored procedure will be nested transaction procedure, whereby it will call few stored procedures that have transaction in them. If either one of the inner stored procedures hits an error, then will rollback all, such as
Begin Try
Begin Tran
Exec Stored Proc 1 (with begin tran inside)
Exec Stored Proc 2 (with begin tran inside)
Exec Stored Proc 3 (with begin tran inside)
Exec Stored Proc 4 (with begin tran inside)
Exec Stored Proc 5 (with begin tran inside)
Commit Tran
End Try
Begin Catch
Catch exception then roll back tran
End Catch
The problem is the transaction count after execute the inner stored procedures are mismatched, however if I didn't open a transaction in the inner stored procedure, it won't rollback. Can anyone give me some suggestions?
Committing inner transactions is ignored by the SQL Server Database Engine. The transaction is either committed or rolled back based on the action taken at the end of the outermost transaction. If the outer transaction is committed, the inner nested transactions are also committed.
Nesting Transactions
I have a stored procedure in a loop that is called about 100 times for about fifteen minutes; once per day. The stored procedure contains deletion statements. What is the best practice for error handling on the client side after executing the stored procedure.
I simply use On Error Resume Next meaning if the stored procedure fails or times out; it is simply called again on the next iteration. I have 'SET XACT_ABORT ON' in the stored procedure to ensure that the explicit transaction in the stored procedure is rolled back if the command object times out in VB6. The stored procedure passes an error code as an output variable back to the program; but I am wandering if anything else is required.