文章主要描述的是 SQL Server2005捕捉錯誤的2種好用方法,在實際操作中任何程式在運作的過程中都可能出現錯誤,包括在SQL Server資料庫中執行Transact-SQL也不例外。如果在Transact-SQL中發生了錯誤。
其一般有兩種捕捉錯誤的方法,一種是在用戶端代碼(如C#、Delphi等)中使用類似try...catch的語句進行捕捉;另外一種就是在 Transact-SQL中利用Transact-SQL本身提供的錯誤捕捉機制進行捕捉。如果是因為Transact-SQL語句的執行而産生的錯誤, 如鍵值沖突,使用第一種和第二種方法都可以捕捉,但是如果是邏輯錯誤,使用用戶端代碼進行捕捉就不太友善。是以,本文就如何使用Transact-SQL 進行錯誤捕捉進行了讨論。
一、非緻命錯誤(non-fatal error)的捕捉
通過執行Transact-SQL而産生的錯誤可分為兩種:緻命錯誤(fatal error)和非緻命錯誤(non-fatal error)。在Transact-SQL中隻可以捕捉非緻命錯誤(如鍵值沖突),而無法捕捉緻命錯誤(如文法錯誤)。在Transact-SQL中可以 通過系統變量@@ERROR判斷最近執行的一條語句是否成功執行。如果發生了錯誤,@@Error的值大于0,否則值為0。下面舉一個例子說明 @@ERROR的使用。
假設有一個表table1,在這個表中有兩個字段f1,f2。其中f1是主鍵。
INSERT INTO table1 VALUES(1, 'aa')
INSERT INTO table1 VALUES(1, 'bb') --這條語句将産生一個錯誤
IF @@ERROR > 0
PRINT '鍵值沖突'
當執行第二條語句時發生鍵值沖突錯誤,@@ERROR被賦為錯誤号2627,是以輸出結果顯示'鍵值沖突'。使用@@ERROR系統變量時需要注 意,@@ERROR隻記錄最近一次執行的Transact-SQL語句所發生的錯誤,如果最近一次執行的Transact-SQL沒有發生錯 誤,@@ERROR的值為0。是以,隻能在被捕捉的那條Transact-SQL語句後使用@@ERROR。
在SQL Server中,不僅可以捕捉系統提供的錯誤,還可以自定義錯誤。有兩種方法可以定義錯誤資訊。
1、使用sp_addmessage系統存儲過程添加錯誤資訊,然後使用RAISERROR抛出錯誤。
sp_addmessage将錯誤号,錯誤級别、錯誤描述等資訊添加到系統表中,然後使用RAISERROR根據相應的錯誤号抛出錯誤資訊。使用者自 定義的資訊應該從50001開始。
EXEC sp_addmessage @msgnum = 50001, @severity = 16, @msgtext = 'sql encounter an error(%s).', @lang = 'us_english' EXEC sp_addmessage @msgnum = 50001, @severity = 16, @msgtext = 'sql遇到了一個錯誤(%1!).' |
如果使用的SQL Server捕捉錯誤版本是非英語版本,在添加本地錯誤資訊時必須首先添加英文的錯誤資訊。錯誤描述可以象c語言中的printf的格式字元串一樣使用參 數,如%s、%d。但要注意的是在英文版的錯誤資訊中要使用%s、%d等形式,而在本地化的錯誤資訊中要使用%1!、%2!等形式,在每個%?(1 <= ? <= n)後需要加一個!,而且%?的數目必須和英文版的錯誤資訊的參數一緻。
在未插入本地化錯誤資訊時,RAISERROR将使用英文版的錯誤資訊。當插入本地化錯誤資訊時,RAISERROR使用本地化的錯誤資訊。
RAISERROR(50001, 16, 1, '測試')
輸出的結果:
伺服器: 消息 50001,級别 16,狀态 1,行 1
sql遇到了一個錯誤(測試).
其中'測試'字元串通過%1傳入本地化的錯誤描述字元串中。
2、直接使用RAISERROR将錯誤抛出。
使用第一種方法雖然使Transact-SQL語句看上去更整潔(這種方法類似于在程式設計語言中使用常量定義錯誤資訊,然後在不同的地方通過錯誤編号 引用這些錯誤資訊。),但是這樣做卻使錯誤資訊和資料庫的耦合度增加,因為如果将這些帶有RAISERROR的Transact-SQL放到别的SQL Server資料庫上執行,由于在其它的資料庫中還未添加錯誤資訊,是以會産生RAISERROR調用錯誤,除非使用sp_addmessage将所需的 錯誤資訊再加入到其它的資料庫中。
基于上述原因,RAISERROR不僅可以根據錯誤代碼抛出錯誤資訊,也可以直接通過錯誤描述格式字元串抛出錯誤資訊。
RAISERROR('sql遇到了一個錯誤(%s)', 16, 1, '測試')