在我們使用SQL時,可能會需要執行許多新增、修改的動作,但是可能會因為某一行邏輯錯誤造成例外(Exception)的發生,
而在發生例外錯誤的時候,程式會繼續執行完還是就停止執行了呢?答案是會繼續執行
這個問題可能很多人知道,但是曾經詢問前輩得到的是不同答案,讓我很驚訝
在這裡做個實驗驗證
測試EXCEPTION
我們先建立測試TABLE
IF OBJECT_ID('tempdb.dbo.#TBL') IS NOT NULL DROP TABLE #TBL
CREATE TABLE #TBL(ITEM INT)
接下來故意在第二次INSERT之後產生除以零的錯誤
INSERT INTO #TBL(ITEM) VALUES(1)
INSERT INTO #TBL(ITEM) VALUES(2)
SELECT 2/0
INSERT INTO #TBL(ITEM) VALUES(3)
SELECT * FROM #TBL
結果為如下
完整範例
IF OBJECT_ID('tempdb.dbo.#TBL') IS NOT NULL DROP TABLE #TBL
CREATE TABLE #TBL(ITEM INT)
INSERT INTO #TBL(ITEM) VALUES(1)
INSERT INTO #TBL(ITEM) VALUES(2)
SELECT 2/0
INSERT INTO #TBL(ITEM) VALUES(3)
SELECT * FROM #TBL
實務上常常先對Table DELETE再去INSERT,如果INSERT遇到Primary Key衝突不就重新執行沒錯就沒事了
因此我會在執行多行的執行緒習慣包一層Try/Catch,使用方法和C#/C++幾乎相同,範例如下
Try/Catch範例
BEGIN TRY
--在這裡放你要執行的SQL語法
END TRY
BEGIN CATCH
--DB查詢用
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage,
ERROR_LINE() AS ErrorLine,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState
--系統拋回訊息用
DECLARE @ErrorMessage As VARCHAR(1000) = CHAR(10)+'錯誤代碼:' +CAST(ERROR_NUMBER() AS VARCHAR)
+CHAR(10)+'錯誤訊息:'+ ERROR_MESSAGE()
+CHAR(10)+'錯誤行號:'+ CAST(ERROR_LINE() AS VARCHAR)
+CHAR(10)+'錯誤程序名稱:'+ ISNULL(ERROR_PROCEDURE(),'')
DECLARE @ErrorSeverity As Numeric = ERROR_SEVERITY()
DECLARE @ErrorState As Numeric = ERROR_STATE()
RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);--回傳錯誤資訊
END CATCH
在CATCH的地方,因為發生Exception會跳至BEGIN CATCH執行,當系統呼叫時會被系統認定為沒錯誤
因此使用RASERROR來故意錯誤訊息觸發
在這裡我們套用剛剛範例使用Try/Catch機制
IF OBJECT_ID('tempdb.dbo.#TBL') IS NOT NULL DROP TABLE #TBL
CREATE TABLE #TBL(ITEM INT)
BEGIN TRY
INSERT INTO #TBL(ITEM) VALUES(1)
INSERT INTO #TBL(ITEM) VALUES(2)
SELECT 2/0
INSERT INTO #TBL(ITEM) VALUES(3)
SELECT * FROM #TBL
END TRY
BEGIN CATCH
--DB查詢用
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage,
ERROR_LINE() AS ErrorLine,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState
--系統拋回訊息用
DECLARE @ErrorMessage As VARCHAR(1000) = CHAR(10)+'錯誤代碼:' +CAST(ERROR_NUMBER() AS VARCHAR)
+CHAR(10)+'錯誤訊息:'+ ERROR_MESSAGE()
+CHAR(10)+'錯誤行號:'+ CAST(ERROR_LINE() AS VARCHAR)
+CHAR(10)+'錯誤程序名稱:'+ ISNULL(ERROR_PROCEDURE(),'')
DECLARE @ErrorSeverity As Numeric = ERROR_SEVERITY()
DECLARE @ErrorState As Numeric = ERROR_STATE()
RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);--回傳錯誤資訊
END CATCH
即可產生以下的錯誤訊息傳至系統的Exception消息
而我們最關心的資料表到底進去了多少資料呢?
實驗成功
建議此方法可以使用在Stored Procedures內,連錯誤的程序名稱也能監控到
如有觀念錯誤,請不吝指教