Can I open 2 transactions with different names - sql

Can I have 2 transactions in a stored procedure like below? If I rollback TRAN1, does it rollback all TRAN2? I am lost here, any feedback will help. Thanks in advance
BEGIN TRANSACTION TRAN1
WHILE(...)
BEGIN
BEGIN TRANSACTION TRAN2
BEGIN TRY
.....
.....
.....
COMMIT TRANSACTION TRAN2
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION TRAN2
END CATCH
END
COMMIT TRANSACTION TRAN1

No matter ,how many transactions you have ,Outer rollback rollbacks all the transactions..
When you nest transactions like in your case,each committ/rollback increases or decreases ##trancount..
From MSDN..
Each BEGIN TRANSACTION statement increments ##TRANCOUNT by one. Each COMMIT TRANSACTION or COMMIT WORK statement decrements ##TRANCOUNT by one.
ROLLBACK TRANSACTION that uses the transaction name of the outermost transaction in a set of nested transactions rolls back all of the nested transactions and decrements ##TRANCOUNT to 0
See this as well :A SQL Server DBA myth a day: (26/30) nested transactions are real
Below is demo to test this behaviour..
if object_id('t1','u') is not null
drop table t1
create table t1
(
id int
)
go
begin tran outertran
select ##trancount--1
insert into t1
select 1
begin tran innertran
select ##trancount--2
insert into t1
select 2
/**below throws error,since you can reference only outer transaction
-referrring inner tran is not legal
***/
--rollback tran innertran
/***
error you get by uncommneting above
Msg 6401, Level 16, State 1, Line 20
Cannot roll back innertran. No transaction or savepoint of that name was found.
**/
commit tran innertran
select ##trancount--1
rollback --rollbacks all
select * from t1
References :
http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630-nested-transactions-are-real/

Related

The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION, but still getting an error

Simple query:
Before the UPDATE, the value of EffectiveStartDt is NULL
After the UPDATE and the ROLLBACK, I want it to go back to NULL
begin tran t1
update MasterPayor
set EffectiveStartDt = '2020-09-17'
where MasterPayorId = 1
commit
rollback tran t1
I have defined the transactions, but I'm still getting the Rollback error
The COMMIT commits the update to the Database and clears the transaction begun with the matching BEGIN TRAN, hence the error when you try to rollback. If you want to ROLLBACK use the ROLLBACK without the COMMIT:
begin tran t1
update MasterPayor
set EffectiveStartDt = '2020-09-17'
where MasterPayorId = 1
rollback tran t1

The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction - 'Msg 3931, Level 16, State 1

I use SQL Server 2014 and I have run this test T/SQL.
BEGIN TRY
BEGIN TRANSACTION T1
CREATE TABLE aa9
(
A int
)
SAVE TRANSACTION S1
INSERT INTO aa9 (A) VALUES ('aa')
COMMIT TRANSACTION T1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION S1
PRINT 'Error ..... '
;throw
END CATCH
Why do I get this error:
Msg 3931, Level 16, State 1, Line 17
The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.
Should I be able to Rollback the transaction to my SavePoint transaction?
You can really only rollback Save Transactions if your XACT_State() isn't -1.
This doesn't really apply to Insert Statements as that will blow the XACT_State() of all the transactions even if you rollback the save point.
So you can use it for stuff like Dividing By Zero and Conversion Errors but SQL Server isn't as sophisticated as you would hope.
However you can get some form of nested transactions as provided you add a bunch of checking as shown below.
Obligatory link to MSDN:https://learn.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sql?view=sql-server-ver16
DROP TABLE IF EXISTS aa9;
BEGIN TRANSACTION T2;
BEGIN TRY
CREATE TABLE aa9
(
A int
)
PRINT 'Starting T2'
SAVE TRANSACTION T2;
INSERT INTO aa9(A) VAlUES (1);
PRINT 'Starting T3'
BEGIN TRANSACTION T3
SAVE TRANSACTION T3
BEGIN TRY
INSERT INTO aa9 (A) VALUES (2)
PRINT 'Forcing Error that doesn''t blow XACT_STATE()'
SELECT 1/0 --Comment This Line To See Difference
INSERT INTO aa9(A) VALUES ('A')
PRINT 'Committing T3'
COMMIT TRANSACTION T3
END TRY
BEGIN CATCH
PRINT 'Rolling Back T3'
ROLLBACK TRANSACTION T3;
THROW
END CATCH
COMMIT TRANSACTION T2;
END TRY
BEGIN CATCH
IF XACT_STATE() = -1
BEGIN
ROLLBACK TRANSACTION
PRINT 'Error ..... '
END
ELSE
BEGIN
COMMIT TRANSACTION T2;
PRINT 'Preserving T2..... '
END;
throw
END CATCH
GO
SELECT * FROM aa9

Rollback an entire stored procedure

I have a stored procedure with multiple update statements.I dont want to use try catch.How can I rollback the stored procedure and get back the original table?
can something like this work -
begin transaction t1
spName
rollback transaction t1
Yes you can wrap everything into a sproc into a transaction
begin tran
exec testproc
commit tran
--rollback tran --for condition
It works fine even for commit as well rollback
If for inside the sproc you need to open another transaction then you need to capture
DECLARE #vTranCount INT = ##TRANCOUNT
--Commit
IF (#vTranCount = 0 AND ##TRANCOUNT <> 0) COMMIT TRANSACTION --Commit if the Tran is created by this sproc
--rollback during catch
IF(#vTranCount = 0 AND ##TRANCOUNT > 0) ROLLBACK TRANSACTION --Rollback if the Tran is created by this sproc

Rollback of nested transaction throwing error in TSQL

Here is a snippet of what I am trying to achieve. I have a nested transaction 'tran2', which I can't rollback
SELECT 'Before', * FROM [table] WHERE field ..
BEGIN TRAN tran1
UPDATE [table] set field ... WHERE field ..
BEGIN TRAN tran2
SELECT 'During', * FROM [table] WHERE field ..
select ##trancount as 'transactioncount'
rollback tran tran2
rollback TRAN tran1
SELECT 'After', * FROM [table] WHERE field ..
is throwing me this error
Msg 6401, Level 16, State 1, Line 13
Cannot roll back tran2. No transaction or savepoint of that name was found.
however the ##trancount is giving me 2 transactions at that point
Instead of begin trans tran2, use save transaction tran2.
This creates a save point within the outer transaction, which you can rollback to.

Nested transaction can't be rolled back

I have SQL Server 2008 and want to do such a transaction:
begin transaction oo;
......
begin try
save transaction xx;
alter table ....; -- this will fail
alter table ....;
alter table ....;
end try
begin catch
rollback transaction xx; -- error here
end catch;
......
commit transaction oo;
At rollback transaction xx;, I get the message
3931 The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.
What am I doing wrong here?
Update To explain the scenario:
There is a big transaction "oo", which will change the table structures of the database from product version X to product version Y.
In the nested transactions, user-specific-tables should be tried to be changed (= inner transaction).
If an user-specific-table is somehow corrupted, the whole product-upgrade process should not be rolled back.
On the other hand, the user-specific-tables should not be upgraded if something else failed during the main product table upgrade (outer transaction).
Reference
you have to use this line inside CATCH block
ROLLBACK TRANSACTION;
which will rollback all transaction,
when you use this one in your above statement (posted in Q) then it will
give us error
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
for it you have to put this line in TRY block
COMMIT TRANSACTION oo;
then finally your statement like that
BEGIN TRANSACTION oo;
BEGIN TRY
SAVE TRANSACTION xx;
CREATE TABLE test (ID INT); -- this will fail from second time
SELECT 3;
COMMIT TRANSACTION oo;
END TRY
BEGIN catch
ROLLBACK TRANSACTION;
END CATCH;
UPDATE after comment
BEGIN TRY
BEGIN TRANSACTION xx1;
select 1; -- this will always success
COMMIT TRANSACTION xx1;
BEGIN TRANSACTION xx2;
CREATE TABLE test (id int); -- this will fail from second time
COMMIT TRANSACTION xx2;
BEGIN TRANSACTION xx3;
select 3; -- this will fail from second time
COMMIT TRANSACTION xx3;
END TRY
BEGIN catch
ROLLBACK TRANSACTION
END CATCH;