群里一個(gè)朋友遇到一個(gè)TRY CATCH的小問題,測試后發(fā)現(xiàn)是自己從來沒有考慮的情況,寫篇blog加深下印象
--=========================================================
在MSDN上對TRY CATCH有如下描述:
對 Transact-SQL 實(shí)現(xiàn)與 Microsoft Visual C# 和 Microsoft Visual C++ 語言中的異常處理類似的錯(cuò)誤處理。Transact-SQL 語句組可以包含在 TRY 塊中。如果 TRY 塊內(nèi)部發(fā)生錯(cuò)誤,則會(huì)將控制傳遞給 CATCH 塊中包含的另一個(gè)語句組。
--=========================================================
在TRY CATCH未出現(xiàn)之前,我們使用@@ERROR,ERROR_STATE()等來判斷語句是否正常運(yùn)行,再根據(jù)情況來處理事務(wù),隨著TRY CATCH的出現(xiàn),我們可以將事務(wù)語句寫成如下方式:
--開啟事務(wù)BEGIN TRAN BEGIN TRY --執(zhí)行一些邏輯操作 INSERT INTO TB1(ID)VALUES(1) --提交事務(wù) COMMIT TRANEND TRYBEGIN CATCH --回滾事務(wù) ROLLBACK TRANEND CATCH
可當(dāng)我們執(zhí)行以下語句(不創(chuàng)建臨時(shí)表#TB)
BEGIN TRAN BEGIN TRY INSERT INTO #TB SELECT 1 PRINT 'COMMIT TRAN'; COMMIT TRAN;END TRYBEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage ,ERROR_SEVERITY() AS ErrorSeverity ,ERROR_STATE() AS ErrorState PRINT 'ROLLBACK TRAN'; ROLLBACK TRAN;END CATCH
由于#TB沒有創(chuàng)建,因此在執(zhí)行中發(fā)生異常,錯(cuò)誤提示如下:
消息 102,級別 15,狀態(tài) 1,第 24 行“對”附近有語法錯(cuò)誤。
這個(gè)錯(cuò)誤很容易理解,因?yàn)?TB不存在,但這不是重點(diǎn),重點(diǎn)是CATCH部分的語句沒有被執(zhí)行,事務(wù)沒有被提交也沒有被回滾(如果程序中有類似問題,那就嚴(yán)重咯)。
繼續(xù)閱讀MSDN,可以找到如下解釋:
不受 TRY…CATCH 構(gòu)造影響的錯(cuò)誤TRY…CATCH 構(gòu)造在下列情況下不捕獲錯(cuò)誤:嚴(yán)重級別為 10 或更低的警告或信息性消息。嚴(yán)重級別為 20 或更高且終止會(huì)話的 SQL Server 數(shù)據(jù)庫引擎任務(wù)處理的錯(cuò)誤。如果所發(fā)生錯(cuò)誤的嚴(yán)重級別為 20 或更高,而數(shù)據(jù)庫連接未中斷,則 TRY…CATCH 將處理該錯(cuò)誤。需要關(guān)注的消息,如客戶端中斷請求或客戶端連接中斷。當(dāng)系統(tǒng)管理員使用 KILL 語句終止會(huì)話時(shí)。如果以下類型的錯(cuò)誤的發(fā)生級別與 TRY…CATCH 構(gòu)造的執(zhí)行等級相同,則 CATCH 塊不會(huì)處理這些錯(cuò)誤:編寫錯(cuò)誤,例如禁止運(yùn)行批處理的語法錯(cuò)誤。語句級重新編寫過程中出現(xiàn)的錯(cuò)誤,例如由于名稱解析延遲而造成在編寫后出現(xiàn)對象名解析錯(cuò)誤。這些錯(cuò)誤會(huì)被返回到運(yùn)行批處理、存儲(chǔ)過程或觸發(fā)器的級別。
經(jīng)過對比分析,我們遇到的問題應(yīng)該屬于“語句級重新編寫過程中出現(xiàn)的錯(cuò)誤,例如由于名稱解析延遲而造成在編寫后出現(xiàn)對象名解析錯(cuò)誤。”的情況。
--==============================================================
如果有類似的問題,我們應(yīng)該如何處理呢?
解決辦法1: 在對#TB處理前先判斷其是否存在
解決辦法2:將對#TB的操作語句放入的EXEC(@SQL)
BEGIN TRAN BEGIN TRY EXEC('INSERT INTO #TB SELECT 1') PRINT 'COMMIT TRAN'; COMMIT TRAN;END TRYBEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage ,ERROR_SEVERITY() AS ErrorSeverity ,ERROR_STATE() AS ErrorState PRINT 'ROLLBACK TRAN'; ROLLBACK TRAN;END CATCH
執(zhí)行以上代碼,會(huì)發(fā)現(xiàn)同樣是嚴(yán)重級別16的錯(cuò)誤,這次可以被傳遞到CATCH塊中處理。--=======================================================
很多人說細(xì)節(jié)決定成敗,學(xué)習(xí)SQL SERVER的路上,有很多類似的小知識(shí)點(diǎn),平時(shí)很難遇到,遇到時(shí)也很容易顛覆下我們自認(rèn)為的“真理”,這個(gè)時(shí)候,多看看MSDN還是很管用的!
新聞熱點(diǎn)
疑難解答
圖片精選