在 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

当用于 TRY...CATCH 构造的 CATCH 块的作用域内时,ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 和 ERROR_STATE 函数仅返回错误信息。用于 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 块中,则 @@ERROR 值必须在相关的 CATCH 块的第一条语句中进行测试和检索。

  • 如果生成错误的语句不在 TRY 块中,则 @@ERROR 值必须在生成错误的语句之后立即在语句中进行测试和检索。

在 CATCH 块的作用域外,@@ERROR 中的错误号是有关 Transact-SQL 代码内错误的唯一可用信息。如果错误使用了 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