程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 基於SQL Server 的Exception Handling - PART I

基於SQL Server 的Exception Handling - PART I

編輯:關於SqlServer


  對於所有的開發人員來說,Exception Handling是我們每天都要面對的事情。對於基於Source Code的Exception Handling,我想大家已經司空見慣了,但是對於Database級別的Exception Handling,就沒有那麼常見了。在這篇文章中,我將會介紹我對於基於Database編程中Exception Handling的一些粗淺的認識:在編寫Stored Procedure時,如何拋出一個可預知的Exception,ADO.NET如何處理從Database拋出的Exception,如何保存基於Database Exception的Error Message,如何在Database和.Net Application之間進行消息的傳遞[注:這裡的Database主要指SQL Server]。

  @@ERROR

  RAISEERROR

  TRY CATCH & Return

  Error message & sys.messages

  ADO.Net Exception Handling

  SqlException

  InfoMessage

  一、  @@ERROR

  @@ERROR是我們經常使用的系統函數,其返回類型為INT,用以表示上一個語句的執行是否遇到錯誤,0便是語句正常執行,非0則以為著某個錯誤的產生。比如下面的一個例子:我在SQL Server Management Studio中執行下面一段簡單的SQL:

DECLARE @result INT
SET @result = 10/0
PRINT @@ERROR
Go

  會得到如下的執行結果:

  由於除零導致錯誤的產生,使@@ERROR的值變成8134。實際上8134是一個Error Number,代表某個系統定義的Error,每個預定義的Error由一個唯一的Error Number來唯一標識。@@ERROR本質上就是返回上一個語句執行遇到的Error的ID號,所以這並不是一個隨機的值,無論是10/0還是100/0,@@ERROR返回的結果都是一樣的。



  由於可以通過@@ERROR得到Error的類型,可以幫助我們在編寫Stored Procedure的過程中,借助這個@@ERROR進行一些流程的控制。比如我們知道Error Number為547代表違反外鍵約束,我們就可以通過@@ERROR的結果是否等於547來進行異常的處理:

UPDATE T_USERS_IN_ROLES SET [USER_ID] = 'dummy text'
IF @@ERROR = 547
PRINT 'The user is not existent'

  通過我們上面一個截圖我們發現,在

  SQL Server Management Studio中執行任何一個語句的時候,如果遇到一個預定義的Error,會打印出相關的Error Message。這些Error Message到底是如何存儲的呢?Error message和Error Numbder又是如何進行關聯的呢?

  實際上,SQL Server通過一個名為sys.messages的系統表來存儲關於Error的一些信息[關於sys.messages,在後續的章節中還會提及]。下面是sys.messages的結構:message_id不僅僅代表message的唯一標識,對於一個預定義的Error,其Error number就是這個message_id。由於Localization的需要,我們需要為不同的語言定義不同的Message,這些Message共享一個message_id, 具體采用何種語言通過luange_id來標識。Severity代表Error的嚴重程度,我將在後續部分專門介紹。is_event_logged是一個Indicator,表明出現該Error是否需要在Event log中進行日志記錄,text當然就是message文本了。

  我們可以通過下面的SQL來進行驗證:

DECLARE @result INT
DECLARE @error INT
SET @result = 5/0
SET @error = @@ERROR
SELECT @error,sys.messages.* FROM sys.messages WHERE message_id = @error
Go



  下面是執行的結果:

  對於@@ERROR,有一點需要特別提醒的是:它僅僅代表前一個語句執行的Error Number,之後任何一段語句的執行都會改變@@ERROR的值,甚至是一個IF語句。我想通過下面一段SQL,你肯定會後一個深刻的認識:

  我們可以看到,一個簡簡單單的IF語句就將@@ERROR從8134變成了0。不過想想也很簡單,IF語句本身也是一個執行語句,在執行過程中並沒有遇到Error,所以@@ERROR應該返回0。這也是我在上面的Sample中通過SET @error = @@ERROR將@@ERROR進行預存的原因。

  @@ERROR實際上代表的是在編寫SQL或者Stored procedure中對異常的識別,大多數我們通過@@ERROR來判斷一段SQL語句是否成功執行,保證沒有遇到不可預知的異常。對於一些可以預知的異常在SQL中又該如何處理呢?

  我發現很多程序員喜歡使用Output參數來處理這些預知的異常。比如:我們需要編寫一個添加User的Stored procedure,user name具有唯一性,添加一個和database中同名的user顯然是不合法的,在很多情況下通過一個Output參數來返回操作最終執行的情況,比如:

CREATE Procedure P_USERS_I
  (
    @user_id      varchar(50),
    @user_name  nvarchar(256),
    @flag        INT OUTPUT
  )
AS
IF(EXISTS(SELECT * FROM dbo.T_USERS WHERE LOWERED_USER_NAME = LOWER(@user_name) OR [USER_ID] = @user_id))
  BEGIN
    SET @flag = -1
    RETURN
  END  
INSERT INTO dbo.T_USERS
      ([USER_ID]
      ,[USER_NAME]
      ,LOWERED_USER_NAME)
   VALUES(@user_id, @user_name, LOWER(@user_name))  
SET @flag = @@ERROR

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved