明示カーソルと暗黙カーソル
カーソル(CURSOR) とは、主に問い合わせ(データ操作も含む)を行なうための情報を管理する作業領域をあらわすための「タグ」のようなものである。
このカーソルにユーザーが名前を付けているものを 明示カーソル と呼ぶ。
暗黙カーソル では Oracle によって用意されている名前の無い作業領域を使用している。
明示カーソルを使用するとカーソルの再利用や %ROWTYPE などを使用してメタデータ(定義情報)を PL/SQL 上などから容易にフェッチ(取り出し)することができる。
暗黙カーソルを使用した SELECT 文による FOR ループ
カーソルを使用せずに FOR の制御リストに記述することでループ変数に結果レコードを代入する。
SELECT した結果セットが存在しない場合にはループ処理は発生しない。
SQLPlus の場合には実行の前に SET SERVEROUTPUT ON を実行しておく。
CREATE OR REPLACE PROCEDURE RIVUS.STEP01_SELECT1
IS
BEGIN
FOR vRec IN (
SELECT 'data1' COLNAME_1 FROM DUAL
UNION ALL SELECT 'data2' COLNAME_1 FROM DUAL
) LOOP
-- 暗黙カーソルの各属性は使用できない。
DBMS_OUTPUT.PUT(NVL(TO_CHAR(SQL%ROWCOUNT),'NULL') || ':');
DBMS_OUTPUT.PUT_LINE(vRec.COLNAME_1);
END LOOP;
END;
/
--
-- 実行結果
SQL> call step01_select1();
NULL:data1
NULL:data2
コールが完了しました。
注意:Oracle 10g 現在、暗黙カーソルを使用した FOR ループには 暗黙カーソルの SQL 属性を使用することができない。
明示カーソルを使用した SELECT 文による FOR ループ
暗黙カーソルの例の内容に加えて、プロシージャのパラメータを直接埋め込み、カーソルの引数をデフォルト値指定ありで宣言している(カーソルを使用するときに引数が無くても良い)。
CREATE OR REPLACE PROCEDURE RIVUS.STEP01_SELECT2(P_DATA_1 IN VARCHAR2)
IS
CURSOR cDual(P_DATA_2 VARCHAR2 := 'CURSOR param') IS
SELECT P_DATA_1 COLNAME_1 FROM DUAL
UNION ALL SELECT P_DATA_2 COLNAME_1 FROM DUAL ;
BEGIN
FOR vRec IN cDual('xxx') LOOP
DBMS_OUTPUT.PUT(cDual%ROWCOUNT || ':');
DBMS_OUTPUT.PUT_LINE(vRec.COLNAME_1);
END LOOP;
END;
/
--
-- 実行結果
SQL> call step01_select2('SELECT2');
1:SELECT2
2:xxx
コールが完了しました。
注意: フェッチする前にレコード件数を知るための手段として ROWCOUNT 属性は使用できない。
SELECT の場合にはカーソルの ROWCOUNT 属性は SELECT において取り出した件数をカウントする。そのため検索に一致する結果セットの件数と一致するのは、すべてのフェッチが終了したときである。
明示的なカーソルのオープンとフェッチ処理
上記の例は FOR ループ処理の内部で カーソルのオープンとフェッチ処理が行なわれていたが、それを明示的に行なうループ処理を記述してみる。
CREATE OR REPLACE PROCEDURE RIVUS.STEP01_SELECT3(P_DATA_1 IN VARCHAR2)
IS
CURSOR cDual(P_DATA_2 VARCHAR2 := 'CURSOR param') IS
SELECT P_DATA_1 COLNAME_1 FROM DUAL
UNION ALL SELECT P_DATA_2 COLNAME_1 FROM DUAL ;
vRec cDual%ROWTYPE;
BEGIN
OPEN cDual('yyy') ; -- 引数付きのカーソルをオープン
LOOP
FETCH cDual INTO vRec; -- カーソルの内容をフェッチする
EXIT WHEN cDual%NOTFOUND;
DBMS_OUTPUT.PUT(cDual%ROWCOUNT || ':');
DBMS_OUTPUT.PUT_LINE(vRec.COLNAME_1);
END LOOP;
CLOSE cDual; -- 使用済のカーソルは必ずクローズすること
END;
/
--
-- 実行結果
SQL> call step01_select3('SELECT3');
1:SELECT3
2:yyy
コールが完了しました。
カーソル処理 関連事項