【问题标题】:Where is the Begin/Commit mismatch in this stored procedure?此存储过程中的开始/提交不匹配在哪里?
【发布时间】:2010-11-19 22:14:31
【问题描述】:

我收到以下错误:

EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 0,当前计数 = 1。

当我尝试执行这个存储过程时:

create procedure [dbo].[SynchCustomerSubscriptions] (
  @subscriptions Subscriptions readonly )
as

begin transaction

begin tran SynchTransaction
  begin try
    delete s
    from Subscription s (nolock)
    where s.Customer in (
      select Customer
      from @subscriptions)
    exec AddSubscriptions
      @subscriptions
  end  try
  begin catch
    rollback tran SynchTransaction
    return
  end  catch
commit tran SynchTransaction

有人发现问题了吗?

【问题讨论】:

  • 为什么在另一个事务中有一个嵌套事务,并且只提交/回滚一个事务?我的意思是,当你提交时,你提交SynchTransaction,当你回滚时,你回滚SynchTransaction,但是仍然存在一个事务,即未命名的事务!只是想知道和学习一些东西。 =)

标签: sql sql-server database tsql stored-procedures


【解决方案1】:
begin transaction 

begin tran SynchTransaction 

有时你把这些东西看得太久了,最简单的东西你就忘了。

【讨论】:

    【解决方案2】:

    试试这个...

    create procedure [dbo].[SynchCustomerSubscriptions] (    
      @subscriptions Subscriptions readonly )    
    as    
    
    begin transaction SynchTransaction    
    
    begin tran    
      begin try    
        delete s    
        from Subscription s (nolock)    
        where s.Customer in (    
          select Customer    
          from @subscriptions)    
        exec AddSubscriptions    
          @subscriptions    
      end  try    
      begin catch    
        rollback tran SynchTransaction    
        return    
      end  catch    
    end tran
    commit transaction SynchTransaction  
    

    【讨论】:

      【解决方案3】:

      在存储过程中启动一个命名事务实际上是非常糟糕的。不可能只回滚命名的事务,正如您显然尝试的那样,如果在另一个事务的范围内调用该过程,请参阅MSDN

      命名多个事务在一个 一系列嵌套事务 交易名称对 交易。只有第一个 (最外层)事务名称是 向系统注册。回滚 任何其他名称(有效的除外) 保存点名称)生成错误。

      您可能想要的是一个保存点,它是另一种野兽。如果你想混合嵌套事务、保存点和异常 try/catch 块,事情会更复杂一些。最好使用本文中的模式Exception handling and nested transactions,它考虑了当前@@TRANCOUNT 和异常XACT_STATE

      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) ;
              return;
          end catch   
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-07
        • 1970-01-01
        • 2011-06-29
        • 2012-11-08
        • 1970-01-01
        • 2012-03-12
        相关资源
        最近更新 更多