The company I work at uses stored procedures (and a home-grown ORM) exclusively for all database interaction, selects, updates, deletes.
We have numerous procs that will insert and/or update and/or delete from tables.
When it's required to "transactionalize" an entire proc, then we obviously needed to have our commit
and rollback
statements.
Here's where the question comes.
When there are multiple statements in a transaction that either need to be committed or rolled-back together, then we obviously throw a try/catch block around everything.
Let's assume this example scenario for a script:
set nocount on
create table #test
(
id int primary key identity(1,1),
col varchar(2) not null,
y int not null
)
begin tran
begin try
insert into #test ( col, y ) values ('GA', 4)
update #test set col = 'DO', y = y / 0
insert into #test ( col, y ) values ('aa', 7)
commit
end try
begin catch
select error_message()
rollback
end catch
select * from #test t
drop table #test
Now, this is the way that I would write the script.
Let's assume that the update statement (the 2nd statement) causes an exception. That should then move the focus to the catch block, and thus executing the rollback
command undoing all of the work that was done in the insert
.
THEY say that in order for the rollback
to actually rollback ALL statements instead of the one that caused the exception is to write the script like this:
set nocount on
set xact_abort on ------------------------------------------------
create table #test
(
id int primary key identity(1,1),
col varchar(2) not null,
y int not null
)
begin tran
begin try
insert into #test ( col, y ) values ('GA', 4)
update #test set col = 'DO', y = y / 0
insert into #test ( col, y ) values ('aa', 7)
commit
end try
begin catch
select error_message()
if (xact_state() <> 0) -------------------------------------------------
rollback
end catch
select * from #test t
drop table #test
Now, when I test both of these examples, they both get the same desired result (no records in the table).
What is the point of doing the xact_abort
and xact_state
stuff when just wrapping multiple statements in a try/catch accomplishes the same thing (rolling back multiple statements when there's an exception)?