天天看點

SQL Server2005捕捉錯誤的2種方案

文章主要描述的是 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, '測試')