【问题标题】:Rollback Transaction on Errors错误回滚事务
【发布时间】:2011-11-24 04:34:58
【问题描述】:

我有一个很大的生成脚本。它有多个批次(GO 语句)。第一行是BEGIN TRAN

如果在执行过程中出现任何错误,无论是使用RAISERROR 自己引发的,还是由 SQL Server 引发的,我都想回滚事务。我希望脚本继续执行到最后,然后回滚,而不是在发生任何错误时立即中止执行。

在脚本末尾检查@@error <> 0 似乎还不够,因为如果脚本中的最后一条语句成功,即使前面的语句失败,@@error 也会为 0。

我不能在一开始就声明@rollback BIT,因为脚本被分割成多个批次,所以变量超出了范围。

我明白RAISERROR 并不意味着我的交易会被回滚。

关于以兼容 SQL 2000 的方式实现此功能的最佳方式有什么建议吗?

【问题讨论】:

  • 你没有收到错误:The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
  • 不,我不......即使我更早地引发错误,事务也会在最后提交

标签: sql-server sql-server-2005 transactions


【解决方案1】:

您始终可以使用SET CONTEXT_INFO 传递“带外”信息,稍后使用CONTEXT_INFO() 阅读。如果发生错误,请将上下文信息设置为您在提交前检查的值。

这回答了你关于如何做的问题,但我真的必须首先表达我对为什么这样做的疑问。因为许多错误会中止事务无论如何,所以你可能会盲目地相信继续和回滚是安全的,只是发现没有什么可以回滚,并且在异常发生后你的所有错误脚本承诺。其次,对于不中止事务的异常,做任何工作只回滚还是很值得怀疑的。你的要求太离谱了,我想知道你是否真的了解你所做的一切的所有含义。

【讨论】:

  • 我希望整个脚本运行,以便用户可以获取脚本中需要更正的所有错误的列表....否则他们需要更正一个错误时间。我当然愿意接受有关此事的其他建议。
  • 谢谢。该脚本也有几个 EXEC('...') 语句。 PARSEONLY 会使用它吗?
  • 我认为 SET CONTEXT_INFO 是在 SQL 2005 中引入的
  • @Clint:SET CONTEXT_INFO 在 SQL 2000 中:msdn.microsoft.com/en-us/library/aa259199%28v=sql.80%29.aspx
  • @Jeff:不,仅解析不会处理 EXEC 或 sp_executesql 调用。
【解决方案2】:

一种常见的技术是创建一个临时表并在每批结束时使用样板代码

begin tran
go

create table #errors (errorid int not null)
go

select 1/ 0

declare @error int
set @error = @@error
if @error <> 0 insert into #errors values (@error)  
go

select 1/ 1

declare @error int
set @error = @@error
if @error <> 0 insert into #errors values (@error)    
go

if exists (select * from #errors)
begin
    print 'rolling back transaction'
    select * from #errors
    rollback tran
end
else
begin
    print 'commit transaction'
    commit tran
end
go

if OBJECT_ID('tempdb..#errors') is not null
    drop table #errors
go

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    相关资源
    最近更新 更多