2017-05-31 94 views
2

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

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行的所有行被提取后,光标再次指向第一行,但是在此之后,提取似乎不会发生。我无法理解为什么游标在第二次迭代过程中无法获取第二行和后续行。

+0

你是怎么“打破之间的操作”? – APC

+0

在sql开发人员中,我取消了任务进度窗口 – PTK

回答

3

“什么最后一个记录后会被取将把光标点到第一条记录,或指向空内存区?”。

都没有。我们需要区分游标和结果集。

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

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

“光标指向第一行再取,但似乎并不在此之后发生的”

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

+0

中的操作,谢谢@APC .cursor仅在第一次表迭代后指向最后一条记录。 – PTK

1

您的代码将继续尝试获取下一条记录并提出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