sql >> Base de Datos >  >> RDS >> Sqlserver

¿Necesito usar un bloque try..catch y una reversión explícita en un procedimiento de SQL Server?

La respuesta a su pregunta depende del SET XACT_ABORT ajuste:

Por ejemplo, pruebe el siguiente código. La primera división por 0 genera un error pero continúa la ejecución . La segunda división por cero genera un error y detiene la ejecución:

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

Si XACT_ABORT está activado, los errores anularán la transacción y no necesitará TRY / CATCH.

Si XACT_ABORT está DESACTIVADO, deberá verificar el estado de cada declaración para ver si ocurrió un error:

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

Sin embargo, si alguna vez encuentra un caso en el que necesita TRY / CATCH, es posible que deba hacer algo especial cuando ocurra el error. Si es así, no olvides PROBAR / ATRAPAR el manejo de excepciones:

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