使用 RAISERROR

RAISERROR 是用來將訊息傳回給應用程式,格式與 SQL Server Database Engine 所產生的系統錯誤或警告訊息相同。

RAISERROR 可傳回:

  • 使用 sp_addmessage 系統預存程序所建立的使用者定義錯誤訊息。這些訊息的訊息編號都大於 50000,您可以在 sys.messages 目錄檢視中看到這些訊息編號。

  • 在 RAISERROR 陳述式中指定的訊息字串。

RAISERROR 亦可:

  • 指派特定錯誤號碼、嚴重性和狀態。

  • 要求在 Database Engine 錯誤記錄檔和 Microsoft Windows 應用程式記錄檔中記錄錯誤。

  • 將引數值替代到訊息文字中,這項功能類似於 C 語言的 printf_s 函數。

RAISERROR 和 PRINT 都可用來將資訊或警告訊息傳回給應用程式。可以使用與 C 標準程式庫中 printf_s 函數類似的功能來建立 RAISERROR 傳回的訊息文字,而 PRINT 則只能傳回字元字串或字元運算式。如果 TRY…CATCH 建構的 TRY 區塊中執行嚴重性為 11 到 19 的 RAISERROR,則控制權會轉交給相關聯的 CATCH 區塊。指定 10 或 10 以下的嚴重性會直接使用 RAISERROR 傳回訊息,而不叫用 CATCH 區塊。PRINT 不會將控制權轉交給 CATCH 區塊。

當 RAISERROR 搭配 sys.messages 中使用者定義訊息的 msg_id 使用時,msg_id 會傳回為 SQL Server 錯誤號碼或原生錯誤碼。如果 RAISERROR 是用來搭配 msg_str,而非 msg_id,則傳回的 SQL Server 錯誤號碼和原生錯誤碼為 50000。

使用 RAISERROR 來傳回使用者自訂錯誤訊息時,請在參考該錯誤的每個 RAISERROR 中使用不同的狀態編號。萬一發生錯誤時,這可協助您診斷原因。

使用 RAISERROR 可:

  • 協助疑難排解 Transact-SQL 程式碼。

  • 檢查資料的值。

  • 傳回包含變數文字的訊息。

  • 將執行位置從 TRY 區塊跳到相關聯的 CATCH 區塊。

  • 從 CATCH 區塊將錯誤資訊傳回給呼叫的批次或應用程式。

下例會在傳回應用程式的訊息中替換 DB_ID() 和 DB_NAME() 函數的值:

DECLARE @DBID INT;
SET @DBID = DB_ID();

DECLARE @DBNAME NVARCHAR(128);
SET @DBNAME = DB_NAME();

RAISERROR
    (N'The current database ID is:%d, the database name is: %s.',
    10, -- Severity.
    1, -- State.
    @DBID, -- First substitution argument.
    @DBNAME); -- Second substitution argument.
GO

這個範例以使用者自訂的訊息提供同樣的資訊:

EXECUTE sp_dropmessage 50005;
GO
EXECUTE sp_addmessage 50005, -- Message id number.
    10, -- Severity.
    N'The current database ID is: %d, the database name is: %s.';
GO
DECLARE @DBID INT;
SET @DBID = DB_ID();

DECLARE @DBNAME NVARCHAR(128);
SET @DBNAME = DB_NAME();

RAISERROR (50005,
    10, -- Severity.
    1, -- State.
    @DBID, -- First substitution argument.
    @DBNAME); -- Second substitution argument.
GO

下列程式碼範例會顯示如何在 TRY 區塊內利用 RAISERROR,來使執行跳到相關聯的 CATCH 區塊。它也會顯示如何使用 RAISERROR 來傳回可叫用 CATCH 區塊的錯誤相關資訊。

[!附註]

RAISERROR 只能產生狀態為 1 到 127 的錯誤。因為 Database Engine 可能會引發狀態為 0 的錯誤,我們建議您在傳送 ERROR_STATE 的值給 RAISERROR 的狀態參數之前,先檢查它傳回的錯誤狀態。

BEGIN TRY
    -- RAISERROR with severity 11-19 will cause execution to 
    -- jump to the CATCH block
    RAISERROR ('Error raised in TRY block.', -- Message text.
               16, -- Severity.
               1 -- State.
               );
END TRY
BEGIN CATCH
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT @ErrorMessage = ERROR_MESSAGE(),
           @ErrorSeverity = ERROR_SEVERITY(),
           @ErrorState = ERROR_STATE();

    -- Use RAISERROR inside the CATCH block to return 
    -- error information about the original error that 
    -- caused execution to jump to the CATCH block.
    RAISERROR (@ErrorMessage, -- Message text.
               @ErrorSeverity, -- Severity.
               @ErrorState -- State.
               );
END CATCH;