【问题标题】:SQL Server stored procedure return code is NULL when called from TRY...CATCH block从 TRY...CATCH 块调用时,SQL Server 存储过程返回代码为 NULL
【发布时间】:2016-01-28 22:27:04
【问题描述】:

假设我有以下 SQL Server 存储过程:

CREATE PROC TestSP AS
select 'results selected' as column1
RAISERROR('this is an error',16,1)
--RETURN 3

如果我这样称呼它,

DECLARE @ReturnCode int
EXEC @ReturnCode = TestSP
select @ReturnCode as ReturnCode

返回码将为 -6。如果我ALTER PROC 取消注释存储过程中的--RETURN 3 行,并再次调用它,RETURN 3 将覆盖并导致返回码为 3。

如果我从 TRY...CATCH 块中调用该过程,

DECLARE @ReturnCode int
BEGIN TRY
    EXEC @ReturnCode = TestSP
END TRY
BEGIN CATCH
    PRINT 'An error occurred.'
END CATCH
SELECT @ReturnCode as ReturnCode

返回码将为 NULL。

使用的返回码 (EXEC @ReturnCode = TestSP) 是否与从 TRY...CATCH 块中调用存储过程不兼容?

【问题讨论】:

    标签: sql-server error-handling try-catch raiserror


    【解决方案1】:

    从 TRY...CATCH 块调用时返回码为 NULL 的原因可能与 batch abortion 有关。

    Microsoft SQL Server 为程序员提供了以捕获返回代码的方式执行存储过程的选项,如您所说:

    EXEC @ReturnCode = YourStoredProc
    

    但您也可以选择从 TRY...CATCH 块中调用您的存储过程,像这样

    BEGIN TRY
        EXEC YourStoredProc
    END TRY
    BEGIN CATCH
        <handle error>
    END CATCH
    

    如果您要从 TRY...CATCH 块调用存储过程,使用 EXEC @ReturnCode = YourStoredProc 调用它似乎没有意义,因为正如您所指出的,返回码将为 NULL。 (旁注:如果您的代码中没有 TRY...CATCH 或显式 'RETURN n',则 RAISERROR 会将返回码设置为 -1 表示错误严重性为 11,-2 表示 12 , -3 表示 13 等。但是请注意,小于 20 的严重性不会停止代码的执行。)

    TRY..CATCH 方法为您提供了更多选项和信息来处理错误。在 CATCH 块中,您可以使用以下系统函数(取自 TRY...CATCH documentation):

    • ERROR_NUMBER() 返回错误的编号。
    • ERROR_SEVERITY() 返回严重性。
    • ERROR_STATE() 返回错误状态编号。
    • ERROR_PROCEDURE() 返回发生错误的存储过程或触发器的名称。
    • ERROR_LINE() 返回导致错误的例程中的行号。
    • ERROR_MESSAGE() 返回错误消息的完整文本。文本包括为任何可替代参数提供的值,例如长度、对象名称或时间。

    您可以使用以下代码测试这些函数的输出:

    BEGIN TRY
        EXEC TestSP  --A stored proc fashioned to cause an error
    END TRY
    BEGIN CATCH
        SELECT
        'ERROR_NUMBER()', ERROR_NUMBER(),''
        UNION SELECT
        'ERROR_SEVERITY()',ERROR_SEVERITY(),''
        UNION SELECT
        'ERROR_STATE() ',ERROR_STATE(),''
        UNION SELECT
        'ERROR_PROCEDURE()',0,ERROR_PROCEDURE()
        UNION SELECT
        'ERROR_LINE()',ERROR_LINE(),''
        UNION SELECT
        'ERROR_MESSAGE()',0,ERROR_MESSAGE()
    END CATCH
    

    最后,应该注意的是,当在从 TRY...CATCH 块调用的存储过程中使用 RAISERROR 时,严重性

    【讨论】:

    • 有点明显的说明:这就是 TRY-CATCH 块的设计目的!
    • 这是对我有用的信息。我认为它可能对其他人有用,所以我在 SO 上记录了它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2016-05-06
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 2016-11-03
    • 2014-11-06
    相关资源
    最近更新 更多