T-SQL返回错误代码与RaiseError的区别

8

你好,我正在编写一个存储过程,它将根据每小时的计划执行一批作业,我正在尝试决定是返回错误还是引发错误。假设我会在每个作业内记录错误,这会导致更好的性能和可维护性?

例如:

--使用错误代码

CREATE PROCEDURE Job1
AS
BEGIN

    BEGIN TRY
        --Do some work
    END TRY
    BEGIN CATCH
        --log error
        RETURN 1; --Return 1 for error
    END CATCH
    RETURN 0;

END

CREATE PROCEDURE USP_BatchJob
AS
BEGIN
    BEGIN TRANSACTION;

    DECLARE @Error INT;
    EXEC @Error = Job1;
    IF @Error <> 0
        GOTO ErrorHandling;

    EXEC @Error = Job1;
    IF @Error <> 0
        GOTO ErrorHandling;

    IF @@TRANCOUNT > 0
        COMMIT TRANSACTION;

    RETURN;

ErrorHandling:
    IF @@TRANCOUNT > 0
        ROLLBACK;
END

例如:RaiseError

CREATE PROCEDURE Job1
AS
BEGIN

    BEGIN TRY
        --Do some work
    END TRY
    BEGIN CATCH
        --log error
        RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), ERROR_STATE());
    END CATCH

END

CREATE PROCEDURE USP_BatchJob
AS
BEGIN
    BEGIN TRANSACTION
    BEGIN TRY

    EXEC Job1;

    EXEC Job1;

    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK;
    END CATCH

    IF @@TRANCOUNT > 0
        COMMIT TRANSACTION;

END

后者似乎能够产生更易维护的代码。
1个回答

4

关于代码风格,这可能是一个信仰问题。返回码和异常的主要区别在于异常会继续被传递到调用链中。

一般来说,在我编写的代码中,我使用返回值将存储过程的状态作为“应用程序错误”返回。与您的示例一样,0表示成功,其他任何值都表示失败。每当我在实际代码中调用存储过程时,都会对返回值以及可能出现的任何新错误进行检查。顺便说一下,在SQL Server中,您不能通过“@retval <> 0”检查失败,因为存储过程可以返回NULL。

当然,异常/数据库错误仍然可能发生。想法是一旦识别到异常,就会被记录并处理。系统“错误”变成了应用程序错误。

我遇到的唯一问题是与SQL Server Agent的交互。为此,您需要引发一个错误以“分叉”到错误处理步骤。这可以通过在作业步骤中查看返回值,然后生成一个错误轻松完成。


“因为存储过程可以返回NULL” - 这个说法似乎是不正确的。根据SQL Server 2000 RETURN手册以及SQL Server 2012手册的说明,SQL Server中的存储过程不能返回NULL。 - Andriy M
确实是不正确的。我尝试了一下(使用 SQL Server 2012),得到了这个错误信息:'ReturnNullTest' 存储过程试图返回 NULL 状态,但是该状态是不允许的。将返回状态 0。其余部分非常有帮助。 - Davos
1
@Davos...措辞不够优雅。存储过程不会返回“NULL”,但如果存储过程失败,调用者检测到的返回值是“NULL”。或者,如果存储过程没有“return”语句。 - Gordon Linoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接