是否需要在SQLServer过程中使用TRY...CATCH块和显式回滚?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (29)

如果我正在编写SQLServer(2008r2)过程,并将其包装在一个事务中,是否需要显式地将它封装在一个try..CATCH块中,然后在CATCH块中显式地调用回滚,还是它自己也会退出和回滚?

即:

这是如何做到的:

    begin transaction

    begin try
    delete from....

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

    commit transaction

与:

    begin transaction
    delete from....

    insert into...
    commit transaction
提问于
用户回答回答于

尝试以下代码。第一个除数为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

如果XACT_ABORT是打开的,那么错误将中止事务,您不需要TRY / CATCH.。

如果XACT_ABORT已关闭,您将需要检查每个语句的状态,以确定是否发生错误:

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

但是,如果您发现需要尝试/捕获的情况,则可能需要在错误发生时执行一些特殊的操作。如果是这样,请不要忘记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
用户回答回答于

如果在大多数情况下出现错误,但不是所有情况下都有错误,回滚将自动发生。

如果您希望保证所有错误都回滚,则在BEGINTRANSATSETXACT之前进行SET XACT_ABORT ON。

扫码关注云+社区