2011-11-24 86 views
2

我有一個很大的生成腳本。它有多個批次(GO陳述)。第一行是BEGIN TRAN錯誤回滾事務

如果在執行過程中發生任何錯誤,或者使用RAISERROR提出自己,或者由SQL Server產生,我想要回滾事務。我希望腳本繼續執行直到最後,然後回滾,一旦發生任何錯誤,不會中止執行。

在腳本末尾檢查@@error <> 0似乎不夠用,因爲如果腳本中的最後一條語句成功,@@ error將爲0,即使先前的語句失敗。

我最初不能聲明@rollback BIT,因爲腳本被分割爲多個批次,所以變量超出了範圍。我知道RAISERROR並不意味着我的交易將被回滾。

有關以SQL 2000兼容方式實現此操作的最佳方法的任何建議?

+0

你沒收到錯誤:'提交事務請求有沒有相應的BEGIN TRANSACTION.'? –

+0

不,我不......最後提交事務時提交事務 – Jeff

回答

2

您總是可以使用SET CONTEXT_INFO來傳遞'帶外'信息,並在以後使用CONTEXT_INFO()來閱讀它。如果發生錯誤,請將上下文信息設置爲您在提交之前檢查的值。

這回答你如何做的問題,但我真的不得不表達我對的懷疑,爲什麼這樣做首先。因爲很多錯誤會中止交易無論如何所以你可能盲目地繼續認爲這是安全的繼續和回滾只發現沒有什麼可以回滾,並且在異常之後你的所有錯誤的腳本有承諾。其次,對於例外情況而不是放棄交易,仍然非常有疑問的做任何工作只是爲了回滾。你的請求是如此超出了我所知道的,如果你真的理解你正在做的事情的所有含義,

+0

我想讓整個腳本運行,以便用戶可以獲得腳本中所有需要更正的錯誤的列表否則他們需要一次糾正一個錯誤。我當然願意接受有關此事的其他建議。 – Jeff

+0

'SET PARSEONLY ON' http://msdn.microsoft.com/en-us/library/ms178629.aspx –

+0

謝謝。腳本也有幾個EXEC('...')語句。 PARSEONLY會如何工作? – Jeff

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