2017-05-31 26 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のすべての行がフェッチされた後、カーソルが最初の行を再びポイントしているが、フェッチがこの後に起こっていないように見えます。私はカーソルがテーブルの2番目の反復の間に2番目以降の行をフェッチできない理由を理解できませんでした。

+0

「どのように操作を中断しましたか」 – APC

+0

sqlの開発者では、タスクの進行状況ウィンドウで操作をキャンセルしました。 – PTK

答えて

3

「最後のレコードがフェッチされた後はどうなるのウィルカーソルポイントブランクのメモリ領域への最初のレコードまたはポイントに。?」

どちらもありません。カーソルと結果セットを区別する必要があります。

カーソルは、クエリに関する形成の一部です。すべてのレコードを取得すると、カーソルは「使い果たされました」が変更されません。それ自体は再設定されず、最初からやり直すことはありません。 「テーブルの2番目の反復」はありません。それはnullも返しません。状態を持っています。これはフォームをテストすることができます。 CUR%NOTFOUNDとし、EXITで処理してください。

フェッチは実行されますが、何も返されません。結果セット - 場合によっては変数V1にはが最後に取り込まれた値が含まれています。だから、あなたのテーブルはcol2に多くの繰り返し値を持つべきです。

考えにくい

「最初再び行が、フェッチにカーソルポイントは、この後に起こるようではありません」。カーソルにはORDER BY句がないので、V1の値はランダムなソート順を持つ可能性があることに注意してください。フェッチされた最後のEMPNOは、EMP表の中で最も低い値になります。

+0

@APC .cursorは、最初のテーブルの反復後にのみ最後のレコードを指しています。 – PTK

1

外部からプロシージャコールをキャンセルするまで、あなたのコードは次のレコードをフェッチし、cur%notfoundの状態を出そうとします。

<cursor>%notfoundは、次のレコードが見つからないことが通知されるまで、結果セットの終わりに達した時点を知らないため、それ自体では例外ではありません。それはループを止めるために捕捉し、適切に処理する必要があります。あなたは次のことを実行することで、これを見ることができます

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