【问题标题】:How to rollback a transaction in a stored procedure?如何回滚存储过程中的事务?
【发布时间】:2012-07-17 21:47:48
【问题描述】:

查看 SQL Server 联机丛书,微软似乎有一个(不正确的)method of handling nested transactions in a stored procedure

嵌套事务

显式事务可以嵌套。这主要是为了支持存储过程中的事务,这些事务既可以从已经在事务中的进程调用,也可以从没有活动事务的进程调用。

这个例子继续展示了一个存储过程,它启动了它自己的事务(“无论执行它的任何进程的事务模式如何,这个过程都会强制执行它的事务。”)

CREATE PROCEDURE TransProc @PriKey INT, @CharCol CHAR(3) AS
   BEGIN TRANSACTION InProc
      ...
   COMMIT TRANSACTION InProc;

然后可以在不运行事务的情况下调用此过程:

EXECUTE TransProc 3,'bbb';

显式交易:

BEGIN TRANSACTION OutOfProc;

EXEC TransProc 1, 'aaa';

COMMIT TRANSACTION OutOfProc

他们没有解决的是存储产品时会发生什么:

  • 因错误而失败,但让事务继续运行
  • 因错误而失败,但不会让事务继续运行
  • 遇到错误,但在事务打开的情况下继续执行
  • 遇到错误,但事务回滚后继续执行

没有:

  • SET XACT_ABORT ON
  • @@TRANCOUNT

规范示例中的任何位置。

如果我不知道更好,我会认为那行:

以下示例显示了嵌套事务的预期用途。

应该实际阅读

以下示例展示了如何不使用嵌套事务。

除非有人能对这个 BOL 示例做出正面或反面?

【问题讨论】:

标签: sql-server stored-procedures sql-server-2008-r2


【解决方案1】:

您需要对事务使用 try catch 块。因此,如果您在 catch 块中遇到错误,那么您可以回滚您的事务。

请参阅下面的 sql server 代码。

BEGIN TRANSACTION;

BEGIN TRY
    -- Some code
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH

    ROLLBACK TRANSACTION;
END CATCH;

【讨论】:

    【解决方案2】:
    CREATE PROCEDURE [usp_my_procedure_name]
    AS
    BEGIN
      SET NOCOUNT ON;
      DECLARE @trancount int;
      SET @trancount = @@trancount;
      BEGIN TRY
        IF @trancount = 0
          BEGIN TRANSACTION
          ELSE
            SAVE TRANSACTION usp_my_procedure_name;
    
        -- Do the actual work here
    
        lbexit:
          IF @trancount = 0
          COMMIT;
      END TRY
      BEGIN CATCH
        DECLARE @error int,
                @message varchar(4000),
                @xstate int;
    
        SELECT
          @error = ERROR_NUMBER(),
          @message = ERROR_MESSAGE(),
          @xstate = XACT_STATE();
    
        IF @xstate = -1
          ROLLBACK;
        IF @xstate = 1 AND @trancount = 0
          ROLLBACK
        IF @xstate = 1 AND @trancount > 0
          ROLLBACK TRANSACTION usp_my_procedure_name;
    
        RAISERROR ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message);
      END CATCH
    END
    

    【讨论】:

    • 这段代码很好的解释here.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 2020-04-15
    相关资源
    最近更新 更多