从TRY ... CATCH块调用时,SQL Server存储过程返回码为NULL

时间:2015-10-28 22:59:51

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

假设我有以下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。

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

1 个答案:

答案 0 :(得分:0)

从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或显式&#39; RETURN n &#39;,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时,严重性&lt; = 10甚至不被视为错误,并且不会导致调用代码中的CATCH块火。严重性11+将导致CATCH块触发。在大多数情况下,我们应该使用严重级别16和RAISERROR。