SQL Server Try Catch 異常捕捉
阿新 • • 發佈:2019-01-02
背景
今天遇到一個關於try catch 使用比較有意思的問題。如下一段程式碼:
SELECT @@TRANCOUNT AS A
BEGIN TRY
BEGIN TRAN
SELECT @@TRANCOUNT AS A1
INSERT INTO A2A ( ID1 )
VALUES ( 'A' )
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS A2
ROLLBACK TRAN;
SELECT ERROR_MESSAGE() AS ErrorMessage ,
ERROR_SEVERITY() AS ErrorSeverity ,
ERROR_STATE() AS ErrorState
END CATCH
SELECT @@TRANCOUNT AS B
第一次執行時,無法正常捕捉到錯誤,並執行catch的程式碼,返回錯誤資訊
第二次執行,就能正常捕捉。且後續再執行就都正常了。
同樣的程式碼,執行2次出現完全不同的結果。這是很讓人費解的。
分析
首先 看第一次執行報錯,看這個錯誤的級別編號是16。
try catch 不能捕捉什麼樣的錯誤
嚴重級別為 10 或更低的錯誤,屬於警告或資訊性訊息。
嚴重級別為 20 或更高且終止會話的 SQL Server 資料庫引擎任務處理的錯誤。此類問題過於嚴重資料庫引擎會直接終止會話。所以無法往後繼續執行。
總之,就是能捕捉嚴重級別大於10,且不會嚴重到之前終止會話的錯誤
那我們前面的例子錯誤級別16,的確是屬於可以捕捉的情況。那為什麼會有這個問題。跟執行計劃的產生有關係。因為你第一次執行的時候,SQL server 在需要編譯SQL 語句,產生執行計劃。就是這個時候執行計劃還沒有。所以他無法往下面繼續執行。就無法CATCH到。第二次,以及後面幾次再執行,因為已經快取了執行計劃。所以可以catch到。
我們執行完第一次之後可以檢視對應的執行計劃
然後再執行,就可以成功捕捉了。如果我們把執行計劃清除掉
DBCC FREEPROCCACHE 或者使用option(recomplile)進行重編譯。那麼結果就會是一直無法捕捉。