Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Muss ich einen try..catch-Block und ein explizites Rollback in einer SQL Server-Prozedur verwenden?

Die Antwort auf Ihre Frage hängt vom SET XACT_ABORT ab Einstellung:

Versuchen Sie beispielsweise den folgenden Code. Die erste Division durch 0 löst einen Fehler aus, setzt die Ausführung jedoch fort . Die zweite Division durch Null löst einen Fehler aus und hält die Ausführung an:

begin transaction

set xact_abort off
    
select 1 / 0 -- causes divide by zero error, but continues
select @@trancount -- returns 1

set xact_abort on

select 1 / 0 -- causes divide by zero error and terminates execution
select @@trancount -- we never get here

rollback

Wenn XACT_ABORT eingeschaltet ist, brechen Fehler die Transaktion ab und Sie brauchen kein TRY / CATCH.

Wenn XACT_ABORT AUS ist, müssen Sie den Status jeder Anweisung überprüfen, um festzustellen, ob ein Fehler aufgetreten ist:

begin transaction

delete from...
if @@error <> 0
begin
    if @@trancount > 0
        rollback
    return
end

insert into...
if @@error <> 0
begin
    if @@trancount > 0
        rollback
    return
end

commit

Wenn Sie jedoch jemals einen Fall finden, in dem Sie TRY / CATCH benötigen, müssen Sie möglicherweise etwas Besonderes tun, wenn der Fehler auftritt. Wenn ja, vergessen Sie nicht, die Ausnahmebehandlung zu TRY / CATCH:

begin transaction

set xact_abort on

begin try
    select 1 / 0 -- causes divide by zero error and terminates execution
    select @@trancount -- we never get here
    commit
end try
begin catch
    select xact_state() -- this will be -1 indicating you MUST rollback before doing any other operations
    select @@trancount -- this will probably be one, because we haven't ended the transaction yet
    if xact_state() <> 0
    begin try
        select 'rollback'
        rollback
        
        -- do something to handle or record the error before leaving the current scope
        select 'exception processing here'
        --insert into...
    end try
    begin catch
        -- ignore rollback errors
    end catch
    
end catch