為什麼我們需要 SQL Server 中的異常處理? 讓我們通過一個示例來瞭解 SQL Server 中異常處理的必要性。因此,創建一個 SQL Server 存儲過程,通過執行以下查詢來除以兩個數字。 IF OBJECT_ID('spDivideTwoNumber','P') IS NOT NUL ...
為什麼我們需要 SQL Server 中的異常處理?
讓我們通過一個示例來瞭解 SQL Server 中異常處理的必要性。因此,創建一個 SQL Server 存儲過程,通過執行以下查詢來除以兩個數字。
IF OBJECT_ID('spDivideTwoNumber','P') IS NOT NULL
DROP PROCEDURE spDivideTwoNumber
GO
CREATE PROCEDURE spDivideTwoNumber(
@Number1 INT,
@Number2 INT
)
AS
BEGIN
DECLARE @Result INT
SET @Result = 0
SET @Result = @Number1 / @Number2
PRINT '結果是:' + CAST(@Result AS VARCHAR)
END
當我們把0傳遞給這個存儲過程的第二個參數時,我們會得到一個錯誤
EXEC spDivideTwoNumber 100, 0
以下是 SQL Server Management Studio 中的輸出
消息 8134,級別 16,狀態 1,過程 spDivideTwoNumber,第 10 行
遇到以零作除數錯誤。
結果是:0
我們可以看到,即使遇到了錯誤,SqlServer依然會繼續執行後面的語句,最終列印了結果是:0
所以,上述執行的問題在於,即使程式發生錯誤,它仍然顯示結果,因此用戶有可能感到困惑。
發生異常時 SQL Server 中會發生什麼?
在 SQL Server 中,每當發生異常時,它都會顯示異常消息,然後繼續執行程式。但在 C#、Java、C++ 等編程語言中,每當發生異常時,程式執行就會在異常發生的那一行異常終止。
在上述案例中,這種行為是錯誤的,因為當編程語言中發生錯誤時,它們會直接跳過錯誤後的所有語句的執行,但是在 SqlServer中發生錯誤後,執行不會停止。例如,在上面的存儲過程中,當異常發生時,它仍然顯示不應該發生的 “結果是:0”。
SQL Server 中的異常處理是什麼?
隨著 SQL Server 2005 中引入 Try/Catch 塊,SQL Server 中的錯誤處理現在與 C# 和 Java 等編程語言非常相似。但是,在瞭解使用 try/catch 塊進行錯誤處理之前,讓我們退後一步,瞭解在 2005 年之前的 SQL Server 中如何使用系統函數 RAISERROR 和 @@Error 進行錯誤處理。
在 SQL Server 中使用 RAISERROR 系統函數處理異常
讓我們更改我們在上一個示例中創建的相同存儲過程,如下所示,以使用 Raiseerror 系統函數來處理 SQL Server 中的異常。
IF OBJECT_ID('spDivideTwoNumber','P') IS NOT NULL
DROP PROCEDURE spDivideTwoNumber
GO
CREATE PROCEDURE spDivideTwoNumber(
@Number1 INT,
@Number2 INT
)
AS
BEGIN
DECLARE @Result INT
SET @Result = 0
IF(@Number2 = 0)
BEGIN
RAISERROR('第二個數字不能為0', 16, 1)
END
ELSE
BEGIN
SET @Result = @Number1 / @Number2
PRINT '結果是: ' + CAST(@Result AS VARCHAR)
END
END
當我們再次執行以下語句時
EXEC spDivideTwoNumber 100, 0
以下是 SQL Server Management Studio 中的輸出
消息 50000,級別 16,狀態 1,過程 spDivideTwoNumber,第 11 行
第二個數字不能為0
在上述過程中,如果第二個數字為零,我們使用系統定義的 Raiserror () 函數將錯誤消息返回給調用應用程式。
SQL Server 中的 RaiseError 系統函數是什麼?
SQL Server 中的 RaiseError 系統定義函數採用 3 個參數,如下所示。
RAISERROR('錯誤消息', ErrorSeverity, ErrorState)
- 錯誤消息 :您希望在引發異常時顯示的自定義錯誤消息。
- 錯誤嚴重性 :當我們在 SQL Server 中返回任何自定義錯誤時,我們需要將 ErrorSeverity 級別設置為 16,這表明這是一個一般錯誤,並且該錯誤可以由用戶更正。在我們的示例中,用戶可以通過為第二個參數提供非零值來糾正錯誤。
- 錯誤狀態 : ErrorState 也是 1 到 255 之間的整數值。如果您將錯誤狀態值設置在 1 到 127 之間,RAISERROR() 函數只能生成自定義錯誤。
SQL Server 中的@@Error 系統函數
在 SQL Server 2000 中,為了檢測錯誤,我們使用了@@Error 系統函數。如果有錯誤,@@Error 系統函數返回一個 NON-ZERO 值,否則,ZERO表示前面的SQL語句執行沒有任何錯誤。讓我們修改存儲過程以使用@@ERROR系統函數,如下所示。
ALTER PROCEDURE spDivideTwoNumber(
@Number1 INT,
@Number2 INT
)
AS
BEGIN
DECLARE @Result INT
SET @Result = 0
IF(@Number2 = 0)
BEGIN
RAISERROR('第二個數字不能為0',16,1)
END
ELSE
BEGIN
SET @Result = @Number1 / @Number2
END
IF(@@ERROR <> 0)
BEGIN
PRINT '發生了錯誤'
END
ELSE
BEGIN
PRINT '結果是:' + CAST(@Result AS VARCHAR)
END
END
當我們再次執行以下語句時
EXEC spDivideTwoNumber 100, 0
以下是 SQL Server Management Studio 中的輸出
消息 50000,級別 16,狀態 1,過程 spDivideTwoNumber,第 11 行
第二個數字不能為0
發生了錯誤
SQL Server 中的預定義錯誤術語
每當在程式中發生錯誤,例如將數字除以零、違反主鍵、違反檢查約束等,系統都會顯示一條錯誤消息,告訴我們代碼中遇到的問題。程式中發生的每個錯誤都與四個屬性相關聯。
- 錯誤編號
- 錯誤信息
- 嚴重程度
- 錯誤狀態
比如:
消息 8134(錯誤編號),級別 16(嚴重級別),狀態 1(狀態),遇到除以零錯誤(錯誤消息)
-
錯誤編號 是為 SQL Server 中發生的每個錯誤提供的唯一標識符。對於預定義的錯誤,該值將低於 50,000,對於用戶定義的錯誤,該值必須高於或等於 50,000。在引發自定義錯誤時,如果我們不指定錯誤編號,則預設情況下會將錯誤編號設置為 50000。
-
錯誤信息 是描述發生的錯誤的簡簡訊息,最多 2047 個字元。
-
嚴重程度 這說明錯誤的重要性,範圍在 0 到 24 之間。其中
- 0 到 9:不是服務,可被視為信息或狀態消息。
- 11 到 16: 表示這些錯誤可以由用戶創建。
- 17 到 19:表示這些是用戶無法糾正的軟體錯誤,必須向系統管理員報告。
- 20 到 24:表示致命錯誤,如果發生這些錯誤,可能會損壞系統或資料庫。所以這裡的連接立即與資料庫終止。
-
錯誤狀態 它是一個不那麼重要的任意值,可以在 0 到 127 之間。每當必須在多個地方發生相同的錯誤時,我們都會使用它。
註意:我們可以在“系統消息”表下找到所有預定義錯誤的信息
比如:
select * from sys.messages where language_id = 2052 and message_id = 8134
輸出如下:
message_id | language_id | severity | is_event_logged | text |
---|---|---|---|---|
8134 | 2052 | 16 | 0 | 遇到以零作除數錯誤。 |