La società in cui lavoro utilizza le stored procedure (e un ORM interno) esclusivamente per l'interazione con tutti i database, seleziona, aggiorna, elimina.
Abbiamo numerosi procs che inseriranno e / o aggiorneranno e / o elimineranno dalle tabelle.
Quando è necessario "transazionalizzare" un intero proc, ovviamente abbiamo bisogno di avere le nostre dichiarazioni commit
e rollback
.
Ecco dove arriva la domanda.
Quando ci sono più istruzioni in una transazione che devono essere confermate o riavvolte insieme, ovviamente lanciamo un blocco try / catch attorno a tutto.
Supponiamo questo scenario di esempio per uno 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
Ora, questo è il modo in cui scriverei lo script.
Supponiamo che l'istruzione update (la seconda istruzione) causi un'eccezione. Dovrebbe quindi spostare lo stato attivo sul blocco catch e quindi eseguire il comando rollback
annullando tutto il lavoro eseguito in insert
.
ESSI dicono che, per fare in modo che rollback
esegua effettivamente il rollback di TUTTE le istruzioni anziché quella che ha causato l'eccezione, è necessario scrivere lo script in questo modo:
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
Ora, quando provo entrambi questi esempi, entrambi ottengono lo stesso risultato desiderato (nessun record nella tabella).
Che senso ha fare la roba xact_abort
e xact_state
quando il semplice wrapping di più istruzioni in un try / catch realizza la stessa cosa (ripristinando più istruzioni quando c'è un'eccezione)?