我有一个很大的生成脚本。它有多个批次(GO
语句)。第一行是BEGIN TRAN
如果在执行期间发生任何错误,要么使用RAISERROR
引发自己,要么由SQL Server引发,我想要回滚事务。我希望脚本继续执行直到最后,然后回滚,而不是在发生任何错误时立即中止执行。
在脚本末尾检查@@error <> 0
似乎不够,因为如果脚本中的最后一个语句成功,则@@ error将为0,即使先前的语句失败。
我不能在一开始就声明@rollback BIT
,因为脚本被分割成多个批次,因此变量超出了范围。
我了解RAISERROR
并不意味着我的交易将被回滚。
有关以SQL 2000兼容方式实现此方法的最佳方法的任何建议吗?
答案 0 :(得分:2)
您始终可以使用SET CONTEXT_INFO
传递“带外”信息,稍后使用CONTEXT_INFO()
进行阅读。如果发生错误,请将上下文信息设置为您在提交之前检查的值。
这回答了你如何做到这一点的问题,但我必须首先表达我对为什么这样做的疑虑。对于一个很多错误将中止事务无论如何所以你可能盲目地继续相信可以安全继续和回滚只发现没有什么可以回滚和所有错误的脚本在异常后致力于。其次,对于例外而不是中止交易,做任何工作只是为了回滚它仍然是非常值得怀疑的。你的要求是如此之外,我不知道你是否真的理解你正在做的事情的所有含义。
答案 1 :(得分:1)
一种常见的技术是创建一个临时表,并在每个批处理结束时使用样板代码
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