如何将使用保存点的存储过程放入内部?

时间:2019-03-24 11:30:43

标签: sql sql-server

我正在尝试从存储过程中抛出一个错误,该错误使用一个保存点返回到嵌套状态,但是永远不会抛出该错误。

我进行了一些搜索,发现所有使用RAISERROR的解决方案(没有尝试过),但是Microsoft文档说不应再使用RAISERROR,而应该使用THROW。

这是一个小例子。

CREATE OR ALTER PROC sp_should_throw_error
AS
BEGIN
    SET NOCOUNT ON
    SET XACT_ABORT OFF

    DECLARE @TranCounter INT;  
    SET @TranCounter = @@TRANCOUNT;  
    IF @TranCounter > 0
        SAVE TRANSACTION ProcedureSave;  
    ELSE  
        BEGIN TRANSACTION;  

    BEGIN TRY  
        THROW 50001, 'Spitted out an error.', 1

        IF @TranCounter = 0
            COMMIT TRANSACTION;  
    END TRY

    BEGIN CATCH  
        IF @TranCounter = 0 ROLLBACK TRANSACTION;  
        ELSE IF XACT_STATE() <> -1 ROLLBACK TRANSACTION ProcedureSave;  
    END CATCH  
END

EXEC sp_should_throw_error

我希望任何人都可以向我指出我在这里做错了什么。为什么从未抛出该错误?

1 个答案:

答案 0 :(得分:2)

最后一个THROW块中需要一个CATCH,以重新引发错误。否则,因为您已经抓住并处理了它,所以它不会被提升给客户端。

CREATE OR ALTER PROC usp_should_throw_error
AS
BEGIN
    SET NOCOUNT ON
    SET XACT_ABORT OFF

    DECLARE @TranCounter INT;  
    SET @TranCounter = @@TRANCOUNT;  
    IF @TranCounter > 0
        SAVE TRANSACTION ProcedureSave;  
    ELSE  
        BEGIN TRANSACTION;  

    BEGIN TRY  
        THROW 50001, 'Spitted out an error.', 1

        IF @TranCounter = 0
            COMMIT TRANSACTION;  
    END TRY

    BEGIN CATCH  
        IF @TranCounter = 0 ROLLBACK TRANSACTION;  
        ELSE IF XACT_STATE() <> -1 ROLLBACK TRANSACTION ProcedureSave;  
        THROW;
    END CATCH  
END;
GO