如果我正在编写 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/