使用回滚/提交关闭所有游标,如何克服

Posted

技术标签:

【中文标题】使用回滚/提交关闭所有游标,如何克服【英文标题】:Using roolback/commit colses all cursor, how to over come 【发布时间】:2016-05-23 06:54:29 【问题描述】:

我有 PL/SQL 代码,其中我正在执行插入到表 1 并根据某些条件从表 2 中删除,如果删除成功,则提交所有上述语句并插入表 3,状态为“cond_true”else 回滚所有上述事务并插入 table3 'cond_false' 。如果在此代码中使用了提交和回滚,它将关闭打开的游标,并且必须再次为每个游标重新迭代,否则失败且没有游标打开状态。

OPEN cursor1;       
    Loop            
        fetch cursor1 into tbls;
        exit when cursor1%notfound;                     

            execute immediate  INSERT INTO  table1  SELECT  * FROM table2; 
            -- commit only if below condition is true else rollback;

        BEGIN
            IF  some_condition THEN  
               -- this condition will become true only after the above insert is executed successfully for all rows
                execute immediate   DELETE FROM table2 where some_condition2;

                INSERT INTO table3 values('contition_true');
                -- commit;
            ELSE
                INSERT INTO table3 values('contition_false'); 
                --- first rollback the first insert and then commit only this statement;
            END IF;
        END;
    END LOOP;
close cursor1;   

【问题讨论】:

是什么让您认为光标在提交/回滚时关闭?另外,在这个特定示例中光标的意义何在?您没有引用循环内的光标。 在 oracle 回滚和提交中,关闭所有打开的游标。在上述情况下,游标包含 table1 和 table2 的表名 【参考方案1】:

我不确定提交/回滚关闭光标是什么意思。你说的是哪个光标?您正在循环的光标,还是循环内的删除/插入语句?

提交/回滚将关闭事务,但不会关闭游标。如果是这种情况,以下代码在第二次循环光标时会出错,但您会注意到它不会:

begin
  for rec in (select level lvl from dual connect by level <= 5)
  loop
    dbms_output.put_line('lvl = '||rec.lvl);
    commit;
  end loop;
end;
/

lvl = 1
lvl = 2
lvl = 3
lvl = 4
lvl = 5

也许您在谈论通过提交获取?如果是这样,请查看this AskTom question。

或者你的光标是FOR UPDATE?如果是这样,那么执行提交将释放锁并关闭游标。

就目前情况而言,我在您的示例中看不到任何证据表明您根本需要一个游标循环(或者为什么您需要执行立即语句)。循环内部发生的事情与生成它的光标之间似乎没有联系。如果我是你,我会尝试使用一系列基于静态集的删除/插入来重写整个内容,而不是逐行执行所有操作。

【讨论】:

感谢 Boneist,for 循环将代替光标循环工作。正如我所说,上面给出的代码是一个大型动态过程的示例,它迭代了多组表并且具有不同的结构;所以不能使用静态语句。光标有表名和列名。

以上是关于使用回滚/提交关闭所有游标,如何克服的主要内容,如果未能解决你的问题,请参考以下文章

MySQLdb

何时使用 MySQLdb 关闭游标

oracle如何关闭游标?

游标使用后要关闭,然后要释放吗?

如何使用Oracle的游标?

从 pl/sql 异常块中“一次”关闭所有游标