Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

È necessario utilizzare un blocco try..catch e un rollback esplicito in una procedura di SQL Server?

La risposta alla tua domanda dipende da SET XACT_ABORT impostazione:

Ad esempio, prova il codice seguente. La prima divisione per 0 genera un errore ma continua l'esecuzione . La seconda divisione per zero genera un errore e interrompe l'esecuzione:

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

Se XACT_ABORT è attivo, gli errori interromperanno la transazione e non avrai bisogno di un TRY/CATCH.

Se XACT_ABORT è OFF, dovrai controllare lo stato di ogni istruzione per vedere se si è verificato un errore:

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

Tuttavia, se dovessi trovare un caso in cui devi PROVARE / CATTURA, potresti dover fare qualcosa di speciale quando si verifica l'errore. In tal caso, non dimenticare di PROVARE / CATTURA la gestione delle eccezioni:

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