如何回滚 SQL Server 事务并使用输出参数?

Zac*_*ith 1 sql-server stored-procedures error-handling ssdt sql-server-2016

我试图在存储过程中设置一个输出参数,但我认为当我回滚事务时,我认为我也将分配回滚到@out. 那是对的吗?

如果是这样,我如何返回消息并回滚事务?我正在@out从 C#获取参数。

create PROCEDURE [dbo].[sp]
@out varchar(2000) output
AS
BEGIN
    SET NOCOUNT ON
    BEGIN TRANSACTION
    BEGIN TRY
        SET @OUT = "success";
        COMMIT TRANSACTION
    END TRY

    BEGIN CATCH
        set @out = 'not success';
        ROLLBACK TRANSACTION
    END CATCH
END
Run Code Online (Sandbox Code Playgroud)

我原本是在做一个

SELECT 
    ERROR_NUMBER() AS ErrorNumber,
    ERROR_SEVERITY() AS ErrorSeverity,
    ERROR_STATE() AS ErrorState,
    ERROR_PROCEDURE() AS ErrorProcedure,
    ERROR_LINE() AS ErrorLine,
    ERROR_MESSAGE() AS ErrorMessage;
Run Code Online (Sandbox Code Playgroud)

...但这没有帮助,尽管我更喜欢这种方法。

Pau*_*ite 7

编写此存储过程的更健壮的方法是:

CREATE PROCEDURE dbo.sp
AS
BEGIN
    SET XACT_ABORT, NOCOUNT ON;

    BEGIN TRY
        BEGIN TRANSACTION;

        SELECT 1/0; -- An error!

        /* Other good code omitted*/

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

        DECLARE @Message nvarchar(2048) = ERROR_MESSAGE();
        DECLARE @Severity integer = ERROR_SEVERITY();
        DECLARE @State integer = ERROR_STATE();

        RAISERROR(@Message, @Severity, @State);
        RETURN -1;
    END CATCH;
END;
Run Code Online (Sandbox Code Playgroud)

请注意XACT_ABORTBEGIN TRY.之前的使用和结果。也RAISERROR通常优选THROW用于覆盖在下面的参考的原因,但重要的是:

与 RAISERROR 不同,;THROW 总是中止批处理。

中止批处理会导致未分配任何输出参数。

SQL Server 中的错误处理极端古怪,因此我鼓励您查看 Erland Sommarskog 关于该主题的开创性工作:SQL Server 中的错误和事务处理