共用方式為


在 Transact-SQL 中擷取錯誤資訊

在 Transact-SQL 中取得錯誤資訊的方法有兩種:

  • 在 TRY...CATCH 建構的 CATCH 區塊範圍內,您可以使用下列系統函數:

    • ERROR_LINE() 會傳回發生錯誤的行號。

    • ERROR_MESSAGE() 會傳回要傳給應用程式的訊息文字。文字包括提供給任何可替代參數的值,例如,長度、物件名稱或次數。

    • ERROR_NUMBER() 會傳回錯誤號碼。

    • ERROR_PROCEDURE() 會傳回發生錯誤之預存程序或觸發程序的名稱。如果預存程序或觸發程序內並未發生錯誤,此函數會傳回 NULL。

    • ERROR_SEVERITY() 會傳回嚴重性。

    • ERROR_STATE() 會傳回狀態。

  • 在執行任何 Transact-SQL 陳述式後,您可以立即使用 @@ERROR 函數來測試是否有錯誤,並擷取錯誤號碼。

使用 ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 與 ERROR_STATE

ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 以及 ERROR_STATE 函數需用於 TRY...CATCH 建構的 CATCH 區塊範圍內,才會傳回錯誤資訊。若用在 CATCH 區塊的範圍外,將會傳回 NULL。這些函數會傳回造成叫用 CATCH 區塊的錯誤詳細資訊。只要是在 CATCH 區塊內的任何位置執行,這些函數都會傳回相同的錯誤資訊,即使多次參考這些函數也是一樣。這些函數提供給 Transact-SQL 陳述式的資料,與傳回給應用程式的資料相同。

若是在巢狀 CATCH 區塊內,ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 以及 ERROR_STATE 函數會針對參考它們的 CATCH 區塊,傳回該區塊的特定錯誤資訊。例如,外部 TRY...CATCH 建構的 CATCH 區塊可能會有巢狀的 TRY...CATCH 建構。在此巢狀 CATCH 區塊內,這些函數會傳回叫用內部 CATCH 區塊之錯誤的詳細資訊。外部 CATCH 區塊中的相同函數,則會傳回叫用了該 CATCH 區塊之錯誤的詳細資訊。

下例將說明此情況:在外部 CATCH 區塊參考 ERROR_MESSAGE 時,它會傳回由外部 TRY 區塊所產生的訊息文字;當內部 CATCH 區塊參考 ERROR_MESSAGE 時,則會傳回由內部 TRY 區塊中所產生的文字。此範例也說明,在外部 CATCH 區塊中,ERROR_MESSAGE 一定是傳回外部 TRY 區塊中所產生的訊息,即使在執行了內部 TRY...CATCH 建構後也是一樣。

IF EXISTS (SELECT message_id FROM sys.messages
    WHERE message_id = 50010)
        EXECUTE sp_dropmessage 50010;
GO
EXECUTE sp_addmessage @msgnum = 50010,
    @severity = 16, 
    @msgtext = N'Message text is from the %s TRY block.';
GO
BEGIN TRY -- Outer TRY block.
    -- Raise an error in the outer TRY block.
    RAISERROR (50010, -- Message id.
        16, -- Severity,
        1, -- State,
        N'outer'); -- Indicate TRY block.
END TRY -- Outer TRY block.
BEGIN CATCH -- Outer CATCH block.
    -- Print the error message recieved for this
    -- CATCH block.
    PRINT N'OUTER CATCH1: ' + ERROR_MESSAGE();
    BEGIN TRY -- Inner TRY block.
        -- Start a nested TRY...CATCH and generate
        -- a new error.
        RAISERROR (50010, -- Message id.
            16, -- Severity,
            2, -- State,
            N'inner'); -- Indicate TRY block.
    END TRY -- Inner TRY block.
    BEGIN CATCH -- Inner CATCH block.
        -- Print the error message recieved for this
        -- CATCH block.
        PRINT N'INNER CATCH: ' + ERROR_MESSAGE();
    END CATCH; -- Inner CATCH block.
    -- Show that ERROR_MESSAGE in the outer CATCH
    -- block still returns the message from the
    -- error generated in the outer TRY block.
    PRINT N'OUTER CATCH2: ' + ERROR_MESSAGE();
END CATCH; -- Outer CATCH block.
GO

使用 @@ERROR 擷取資訊

@@ERROR 函數可以用來擷取前一個 Transact-SQL 陳述式所產生的錯誤號碼。@@ERROR 一定要緊接著放在產生錯誤的 Transact-SQL 陳述式之後,才會傳回錯誤資訊。

  • 如果產生錯誤的陳述式是在 TRY 區塊內,則必須在相關聯的 CATCH 區塊的第一個陳述式中,測試和擷取 @@ERROR 的值。

  • 如果產生錯誤的陳述式不在 TRY 區塊內,則必須在產生錯誤的該陳述式之後,立即測試和擷取 @@ERROR 的值。

在 CATCH 區塊的範圍之外,關於 Transact-SQL 程式碼內錯誤的唯一可用資訊就是 @@ERROR 中的錯誤號碼。如果錯誤使用了 sys.messages 中定義的錯誤訊息,您可以依本範例中所述,從 sys.messages 擷取已定義的嚴重性及錯誤訊息文字。

IF EXISTS (SELECT message_id FROM sys.messages
    WHERE message_id = 50010)
        EXECUTE sp_dropmessage 50010;
GO
-- Define a message with text that accepts
-- a substitution string.
EXECUTE sp_addmessage @msgnum = 50010,
    @severity = 16, 
    @msgtext = N'Substitution string = %s.';
GO
DECLARE @ErrorVariable INT;
-- RAISERROR uses a different severity and
-- supplies a substitution argument.
RAISERROR (50010, -- Message id.
    15, -- Severity,
    1, -- State,
    N'ABC'); -- Substitution Value.
-- Save @@ERROR.
SET @ErrorVariable = @@ERROR;
-- The results of this select illustrate that
-- outside a CATCH block only the original
-- information from sys.messages is available to
-- Transact-SQL statements. The actual message
-- string returned to the application is not
-- available to Transact-SQL statements outside
-- of a CATCH block.
SELECT @ErrorVariable AS ErrorID,
    text
FROM sys.messages
WHERE message_id = @ErrorVariable;
GO