【问题标题】:Cursor infinite loop光标无限循环
【发布时间】:2017-05-31 10:45:13
【问题描述】:

这个问题只是出于好奇。我试图找出当没有为游标指定退出条件时会发生什么。获取最后一条记录后会发生什么。光标会指向第一条记录还是指向空白内存区域?为此,我创建了一个具有以下结构的测试表。

create table CURSOR_TEST
  (col1 number,col2 NUMBER
  );

以下是我没有退出条件的匿名块

declare
  cursor CUR is select EMPNO from EMP;
  v1 number;
begin
  open CUR;

  loop
    fetch CUR into V1;
    insert into CURSOR_TEST values(s.nextval,V1);
    commit;
  end loop;

  close CUR;
end;

由于它是无限循环,我需要中断其间的操作。在此之后,当我检查表中的记录时,我可以看到在获取 emp 的所有行之后,游标再次指向第一行,但此后似乎没有进行获取。我不明白为什么 cursor 在表的第二次迭代期间无法获取第二行和后续行。

【问题讨论】:

  • 你是如何“中断操作”的?
  • 在sql developer中我取消了任务进度窗口中的操作

标签: sql oracle plsql


【解决方案1】:

"获取最后一条记录后会发生什么。光标是指向第一条记录还是指向空白内存区域?"

两者都不是。我们需要区分游标和结果集。

光标只是关于查询的一些信息。一旦我们获取了所有记录,游标就“用尽”了,但它并没有改变。它不会重新设置自己并从头开始。没有“表的第二次迭代”。它也不会返回null。它有一个状态,我们可以测试它的形式,例如CUR%NOTFOUND,并使用 EXIT 采取行动。

当我们不这样做时,将执行 fetch 但没有返回任何内容。结果集 - 在您的情况下,变量 V1 包含 最后一个获取的值。所以你的表应该有很多col2中的重复值。

" 光标再次指向第一行,但此后似乎没有进行获取"

这似乎不太可能。请记住,您的游标没有 ORDER BY 子句,因此 V1 的值可能具有随机排序顺序。最后提取的 EMPNO 可能是 EMP 表中的最小值。

【讨论】:

  • 感谢@APC .cursor 仅在第一次表迭代后才指向最后一条记录。
【解决方案2】:

您的代码将继续尝试获取下一条记录并提出cur%notfound 条件,直到您从外部取消过程调用。

<cursor>%notfound 本身并不是一个例外,因为 Oracle 不会知道它何时到达结果集的末尾,直到它被告知未找到下一条记录。这就是您需要捕获然后适当处理以停止循环的内容。

您可以通过运行以下命令来查看:

DECLARE
  CURSOR cur IS SELECT dummy FROM dual;

  v_dummy VARCHAR2(1);
  v_nf_count INTEGER := 0;
  v_f_count INTEGER := 0;
BEGIN
  OPEN cur;
  LOOP
    FETCH cur INTO v_dummy;
    IF cur%NOTFOUND THEN
     v_nf_count := v_nf_count + 1;
     dbms_output.put_line('current %notfound count = '||v_nf_count||'; v_dummy = '||v_dummy);
    ELSIF cur%FOUND THEN
     v_f_count := v_f_count + 1;
     dbms_output.put_line('current %found count = '||v_f_count||'; v_dummy = '||v_dummy);
    END IF;

    EXIT WHEN v_f_count = 10 OR v_nf_count = 10;
  END LOOP;
END;
/

current %found count = 1; v_dummy = X
current %notfound count = 1; v_dummy = X
current %notfound count = 2; v_dummy = X
current %notfound count = 3; v_dummy = X
current %notfound count = 4; v_dummy = X
current %notfound count = 5; v_dummy = X
current %notfound count = 6; v_dummy = X
current %notfound count = 7; v_dummy = X
current %notfound count = 8; v_dummy = X
current %notfound count = 9; v_dummy = X
current %notfound count = 10; v_dummy = X

【讨论】:

    猜你喜欢
    • 2012-08-02
    • 1970-01-01
    • 2011-08-28
    • 2012-01-20
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多