我是否需要在SQL Server过程中使用try..catch块和显式回滚?

Sak*_*o73 17 sql-server sql-server-2008

如果我正在编写一个SQL Server(2008r2)过程,并将其包装在一个事务中,我是否需要将它显式地封装在try..catch块中,然后在catch块中显式调用rollback,否则它将退出自己回滚一样吗?

即:

这是怎么回事

    begin transaction

    begin try
    delete from....

    insert into...
    end try
    begin catch
    rollback transaction
    return
    end catch

    commit transaction
Run Code Online (Sandbox Code Playgroud)

与之比较:

    begin transaction
    delete from....

    insert into...
    commit transaction
Run Code Online (Sandbox Code Playgroud)

感谢您的任何帮助.

Pau*_*ams 19

您的问题的答案取决于SET XACT_ABORT设置:

指定当Transact-SQL语句引发运行时错误时,SQL Server是否自动回滚当前事务.

当SET XACT_ABORT为ON时,如果Transact-SQL语句引发运行时错误,则终止并回滚整个事务.

当SET XACT_ABORT为OFF时,在某些情况下,仅回滚引发错误的Transact-SQL语句并继续处理事务.根据错误的严重程度,即使SET XACT_ABORT为OFF,也可以回滚整个事务.OFF是默认设置.

SET XACT_ABORT不会影响编译错误,例如语法错误.

例如,尝试以下代码.第一个除以0会引发错误,但会继续执行.第二次除零会引发错误,手停止执行:

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
Run Code Online (Sandbox Code Playgroud)

如果XACT_ABORT为ON,则错误将中止事务,并且您不需要TRY/CATCH.

如果XACT_ABORT为OFF,则需要检查每个语句的状态以查看是否发生错误:

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
Run Code Online (Sandbox Code Playgroud)

但是,如果您发现需要TRY/CATCH的情况,则可能需要在发生错误时执行一些特殊操作.如果是这样,请不要忘记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
Run Code Online (Sandbox Code Playgroud)