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

标签 sql-server sql-server-2008

如果我正在编写 SQL Server (2008r2) 过程,并将其包装在事务中,是否需要将其显式包含在 try..catch block 中,然后在 catch block 中显式调用回滚,或者将它会自行退出并回滚吗?

即:

这是怎么做到的:

    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

感谢您的帮助。

最佳答案

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

Specifies whether SQL Server automatically rolls back the current transaction when a Transact-SQL statement raises a run-time error.

When SET XACT_ABORT is ON, if a Transact-SQL statement raises a run-time error, the entire transaction is terminated and rolled back.

When SET XACT_ABORT is OFF, in some cases only the Transact-SQL statement that raised the error is rolled back and the transaction continues processing. Depending upon the severity of the error, the entire transaction may be rolled back even when SET XACT_ABORT is OFF. OFF is the default setting.

Compile errors, such as syntax errors, are not affected by 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

如果 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

但是,如果您发现需要 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

关于sql-server - 我是否需要在 SQL Server 过程中使用 try..catch block 和显式回滚?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10950197/

相关文章:

sql - 在 SQL 中添加总计超过 24 小时的时间

SQL父/子递归调用还是联合?

sql - 在不使用分组或透视的情况下对动态字段表应用搜索条件

sql-server - SQL Server : date function in group by clause

sql-server - SQL Server 2008 将 VARCHAR(50) 转换为唯一标识符

sql-server-2005 - "Type DATE is not a defined system type."

sql-server - 如何使用无 DSN 连接在 Access 中创建直通查询?

sql - 我能否以向后兼容的方式更改 SQL Server 表名?例如添加一个永久别名?

sql - 将 SQL 查询结果保存到 Excel 文件

sql - 多个 id 的更新语句