【问题标题】:ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION - when calling a procedure inside while loopROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION - 在 while 循环内调用过程时
【发布时间】:2021-06-03 18:31:34
【问题描述】:

当我的程序试图在 while 循环中调用另一个程序时,我收到了错误。此外,当错误出现在 while 循环内时,它应该在记录后跳过下一次迭代,但下面的内容会退出循环。有人可以帮我解决这个问题吗?

CREATE PROCEDURE NUMBERS
AS
BEGIN TRY
    BEGIN TRANSACTION

    DECLARE VARIABLES
    UPDATE log_1 table

    DECLARE CURSOR FOR SELECT ANYTHING
    OPEN CURUPD 

    FETCH NEXT FROM CURUPD INTO VARIABLES
    WHILE @@FETCH_STATUS = 0 BEGIN
        BEGIN TRY 
            UPDATE TABLE BASED ON VARIABLES
    
            EXEC procedure_2 VARIABLES
    
            INSERT TABLE BASED ON VARIABLES
        END TRY
        BEGIN CATCH
            Update Log_2 Table
                SCount = SCount-1;
                FCount = Fcount+1;
        END CATCH
        SCount = SCount+1;
        FETCH NEXT FROM CURUPD INTO VARIABLES
    END 
    CLOSE CUR
    DEALLOCATE CUR

    UPDATE LOG_1;
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION
    UPDATE LOG_1 Table
END CATCH

【问题讨论】:

  • 我不会假装理解这些——当我把它放在 SSMS 中时,它会给出一大堆语法错误。但是我可以评论说,在提交/回滚事务以确保存在之前,检查@@TRANCOUNT 通常是值得/必要的。
  • 因此,如果我在我的 while 循环中调用一个过程,它将是该特定过程的单独事务。我将如何保存在 while 循环中调用我的存储过程之前发生的事务。另外,我想在该特定迭代的整个过程完成后提交我的代码。我不想在两者之间提交代码,所以如果出现错误,我可以简单地回滚更改。
  • 所以如果我在代码的每个部分提交我的事务让我们说在调用过程之前,在第二个过程中,如果我在过程之后执行插入语句时出错,那么我会无法回滚更改。我该如何处理这部分?
  • 您真的需要涵盖所有交易和每个 SP 调用的单个交易吗?或者你可以把它们放在 SP 里面吗?你有没有考虑过使用savepoints

标签: sql-server tsql while-loop cursor procedure


【解决方案1】:

我们不知道您的procedure_2 中包含什么代码。这段代码中可能有事务。

您必须了解事务是会话的状态,并且根据定义,不可能有许多事务纠缠在不同的代码中不同的程序。

根据定义,因为事务是代码的原子执行。原子可以是非原子的吗?一个事务可以有“子事务”吗?

由于 Microsoft SQL Server 支持嵌套事务,BEGIN TRANSACTION 的计数对于了解何时需要执行 COMMITROLLBACK 非常重要。

SQL Server 使用嵌套事务的非对称模型:

  1. 第一个 ROLLBACK 通过取消结束事务并删除所有修改
  2. 最后一个COMMIT(在BEGIN TRAN的等效数量)结束 事务并最终接受所有数据库修改

您有两种不同的方式来让代码正确管理这种行为。

  1. 是阅读@@TRANCOUNT来决定是否必须执行ROLLBACKCOMMIT
  2. 是用集成函数知道事务是否存活 XACT_STATE()

我更喜欢最后一个,这样做的代码模板必须是这个:

-- non excepted an non transactionned code
BEGIN TRY
   -- non transactionned code, but excepted
   BEGIN TRANSACTION
   -- transactionned and excepted code
   COMMIT; --> to accept all modification
END TRY
BEGIN CATCH
   IF XACT_STATE() <> 0 --> is the transaction alive ?
      ROLLBACK; --> yes ! cancel it
   THROW; --> throw an new exception identical that the one that causes the CATCH to inform outsided procedures
END CATCH

你必须把每一个程序。

如果您不这样做,您将看到您在标题中输入的错误消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多