2013-02-22 28 views
7

我創建了一個存儲過程,該存儲過程運行許多用於修改數據的命令。如果一切成功,我只想提交交易。我用下面的方式try-catch塊(其中真實的東西我CATCH塊使用RAISERROR返回錯誤消息)這樣做:SQL:Try/Catch在嘗試訪問無法找到的表時沒有發現錯誤

BEGIN TRY 
    BEGIN TRANSACTION 
    UPDATE Table1 SET MyVarcharColumn = 'test' 
    UPDATE Table2 SET MyBitColumn = 1 
    UPDATE Table3 SET MyIntColumn = 42 
    COMMIT TRANSACTION 
END TRY 
CATCH 
    ROLLBACK TRANSACTION 
END CATCH 

這工作我想它的方式。例如,如果我將MyBitColumn設置爲'b'而不是1,則捕獲錯誤,控制流向CATCH,並且事務未提交。

我注意到的一個問題是,如果數據庫中不存在Table3,那麼它會出錯(無效的對象名稱),但CATCH塊永遠不會執行並且事務保持打開狀態。

我想處理這個問題,以處理數據庫被修改的任何(遠程)可能性(或者在這個存儲過程被正確添加,但其中一個表不存在的情況下發生的事情)。

我應該如何處理這些錯誤情況?

- 感謝您的幫助。

回答

9

在腳本的開始處使用SET XACT_ABORT

SET XACT_ABORT ON 

當SET XACT_ABORT爲ON時,如果一個Transact-SQL語句產生 運行時錯誤,整個事務將終止並回滾。

我不認爲這將是可能的:當 他們出現在同一級別的執行爲TRY ... CATCH

以下類型的錯誤不是由CATCH塊處理的構造:

  • 編譯錯誤,如語法錯誤,阻止批處理運行。

  • 語句級別重新編譯期間發生的錯誤,,例如由於 延遲的名稱解析而在編譯後發生的對象名稱解析錯誤。

Ref

下面的例子演示瞭如何用SELECT語句生成的對象名解析錯誤 不是由TRY抓... CATCH 結構,而是由CATCH塊捕獲時同樣選擇 語句中被執行存儲過程。

USE AdventureWorks2012; 
GO 

BEGIN TRY 
    -- Table does not exist; object name resolution 
    -- error not caught. 
    SELECT * FROM NonexistentTable; 
END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_MESSAGE() AS ErrorMessage; 
END CATCH 

未被捕獲的錯誤,並控制傳遞出來的嘗試... CATCH 構造到下一個更高的水平。

+0

謝謝。設置導致事務回滾是有用的。但是,錯誤發生後,它仍然不會執行CATCH塊中的內容。這適用於我的應用程序(因爲無論如何都會向上傳遞錯誤),但如果有人試圖確保CATCH塊因其他原因而執行,則不會這樣做。 – Luke 2013-02-22 01:13:01

+0

啊,明白了,在這種情況下,他們只是沒有被抓到那些類型的錯誤。謝謝! – Luke 2013-02-22 01:21:07

-1
EXECUTE ('SELECT * FROM NonexistentTable'); 
相關問題