回滚完成 - 但是这个错误:EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配

时间:2017-10-17 03:57:49

标签: sql sql-server tsql stored-procedures

我在存储过程中收到此错误。

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

我通读了一些答案,发现如果我没有提交就返回,我就会收到错误。我的存储过程是这样的:

BEGIN TRY
BEGIN
    if @id is null
        BEGIN
        set @id= (SELECT last_sequence_value FROM table_name WHERE sequence_name = 'id') + 1
            BEGIN               
                BEGIN TRANSACTION 

                    -- update SQL statement here 

                    IF @@ROWCOUNT = 0
                    BEGIN                       
                        ROLLBACK TRANSACTION
                        RAISERROR('There was an error getting unique id in the table.',10,1)                    
                        RETURN
                    END
                    IF (@@ERROR <> 0)
                    BEGIN
                        ROLLBACK TRANSACTION
                        RAISERROR('There was an error updating record to the table',10,1)
                        RETURN
                    END
                COMMIT TRANSACTION
            END
        END 
    else 
        BEGIN
            -- some sql select statements
        END
  END
END TRY
BEGIN CATCH
   -- Raise an error with the details of the exception
      RAISERROR(@ErrMsg, @ErrSeverity, 1) WITH SETERROR
END CATCH

从上面的代码中,我正在进行回滚并从存储过程返回。然而,当我在perf测试环境中运行它时,我得到了前面提到的错误。

请帮忙解决这个问题。

4 个答案:

答案 0 :(得分:1)

我已经通过添加

修复了它
IF @@TRANCOUNT > 0
   ROLLBACK TRANSACTION 
在我发出错误之前,在catch块中

感谢大家的精彩投入。

答案 1 :(得分:0)

我有一个用户在我继承的代码中报告了同样的错误,但它是由在 sproc 内部使用事务和 try/catch 以及在 VB.Net System.Transactions 内部调用 sproc 的组合引起的。 TransactionScope 块也是如此。如果 sproc 中出现错误,sproc 会正确回滚那里的所有内容,但它显然也回滚了 VB.Net 事务并造成了不匹配。我的解决方法是从 sproc 中删除事务代码和 try/catch 块,因为如果 sproc 失败或其他处理在 VB.Net 事务中完成,VB.Net 事务将回滚 sproc 内的所有插入/更新块也失败了。希望这会为其他人节省一天的挫败感。

答案 2 :(得分:-1)

这里你应该在开始交易中使用try catch blog。像这样

BEGIN
    if @id is null
        BEGIN
        set @id= (SELECT last_sequence_value FROM table_name WHERE sequence_name = 'id') + 1
            BEGIN               
                BEGIN TRANSACTION 
                    BEGIN TRY
                    -- update SQL statement here 

                    IF @@ROWCOUNT = 0
                    BEGIN                       
                        ROLLBACK TRANSACTION
                        RAISERROR('There was an error getting unique id in the table.',10,1)                    
                        RETURN
                    END
                    IF (@@ERROR <> 0)
                    BEGIN
                        ROLLBACK TRANSACTION
                        RAISERROR('There was an error updating record to the table',10,1)
                        RETURN
                    END

                   END TRY 
                   BEGIN CATCH
                         -- Raise an error with the details of the exception
                       RAISERROR(@ErrMsg, @ErrSeverity, 1) WITH SETERROR
                  END CATCH
                COMMIT TRANSACTION
            END
        END 
    else 
        BEGIN
            -- some sql select statements
        END
  END

答案 3 :(得分:-1)

首先,比较

DECLARE @ErrorVar INT

RAISERROR(N'Message', 16, 1);
IF @@ROWCOUNT <> 0
    PRINT 'Rows <> 0'
IF @@ERROR <> 0
    PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
GO

这个

DECLARE @ErrorVar INT,
    @Error INT,
    @Cnt INT

RAISERROR(N'Message', 16, 1);
SELECT @ERROR = @@ERROR, @Cnt = @@ROWCOUNT
IF @Cnt <> 0
    PRINT 'Rows 0'
IF @ERROR <> 0
    PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
GO

https://docs.microsoft.com/en-us/sql/t-sql/functions/error-transact-sql 因为@@ ERROR在每个执行的语句中被清除并重置,所以在验证语句之后立即检查它,或者将其保存到稍后可以检查的本地变量中。 +