2017-05-31 135 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