PL/SQL の反復制御構造(繰り返し処理)
PL/SQL のループ制御、反復制御構造は、LOOP 〜 、FOR 〜 LOOP、WHILE 〜 LOOP の3種類がある。
FOR ループ:範囲演算子 二重ドット(..) を使用した構文
個人的に使用頻度が最も高いものが FOR ループ構文である。その中でもシンプルな構文が二重ドット(..)を使用した構文である。
他にも SELECT や カーソル を併用した FOR ループ処理、バルク処理による FETCH、FORALL ループ処理によるインサート処理なども記述することができる。
様々なカーソル処理 ⇒ カーソル・ループ処理 、バルクフェッチ 、 バルクインサート
FOR による繰り返し処理
二重ドット(..) を使用した FOR ループの構文は ループの下限と上限を指定することでループ回数を事前に設定する。
FOR オート変数 IN 下限値 .. 上限値 LOOP という形式で設定を行なう(※1: 開始値、終了値ではない)。
このオート変数は PLS_INTEGER 型であり、スコープはループの内部だけで有効な 「 変数宣言が必要のない変数」 (※2)である。
ループ処理の最後に下限値から上限値へと自動的に1ずつインクリメントされる。
FOR オート変数名 IN REVERSE 下限値 .. 上限値 LOOP という形式では、上限値 から 下限値 へと1ずつデクリメントされていく。
(※1) FOR ループは、他の言語で一般的に用いられている from、to、step ± 1 の構文と間違ってしまうことがあるが REVERSE の場合に開始値、終了値のように指定するとループ処理は1回も実行されなくなる。
(※2) ループブロック外でループ変数を参照するためには、ループ内で別の変数に代入する必要がある。
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 --
3 -- 1 〜 3 の 3 回ループ
4 FOR i IN 1..3 LOOP
5 DBMS_OUTPUT.PUT_LINE('ループ変数 i = ' || i);
6 END LOOP;
7 --
8 -- 以下のループは1回も動作しない
9 FOR j IN 1..0 LOOP
10 DBMS_OUTPUT.PUT_LINE('ループ変数 j = ' || j);
11 END LOOP;
12
13 -- SQL*Plus ではスペースのみや改行のみでは出力されない。
14 -- DBMS_OUTPUT.NEW_LINE;
15 DBMS_OUTPUT.PUT_LINE('−−');
16 --
17 -- これは2回のループが発生する
18 FOR k IN REVERSE 0..1 LOOP
19 DBMS_OUTPUT.PUT_LINE('ループ変数 k = ' || k);
20 END LOOP;
21 END;
22 /
ループ変数 i = 1
ループ変数 i = 2
ループ変数 i = 3
−−
ループ変数 k = 1
ループ変数 k = 0
PL/SQLプロシージャが正常に完了しました。
WHILE ループ
WHILE は WHILE 条件式 LOOP の構文でループを制御する。条件式が偽になるとループを抜け出す。
以下の例は無限ループになるが EXIT を利用してループを抜け出している。 LOOP 〜 サンプルと同じ動作。
SQL> BEGIN
2 WHILE (1=1) LOOP
3 DBMS_OUTPUT.PUT_LINE('呼び出されます');
4 EXIT WHEN (1=1) ;
5 DBMS_OUTPUT.PUT_LINE('呼び出されません');
6 END LOOP;
7 DBMS_OUTPUT.PUT_LINE('呼び出されます');
8 END;
9 /
呼び出されます
呼び出されます
PL/SQLプロシージャが正常に完了しました。
PL/SQL には REPEAT 〜 UNTIL(条件式) タイプの構文はない。上の例のような形式で LOOP 〜 と EXIT WHEN または IF 〜 EXIT の構文を変形させて代用する。
LOOP 〜
最も単純なループ構造であるが、あまり使う機会はない。LOOP 単独では無限ループとなるため EXIT 〜 (※) を使用してループ処理を抜ける。
(※) Oracle 11g になって CONTINUE が追加されたが Oracle 10g 以前の PL/SQL には CONTINUE 文は存在しない。IF や GOTO 文 を使って代替表記する。
下の2つの例は同じ動作をする。
IF 文 と EXIT 文の使用によるループ処理の脱出
SQL> BEGIN
2 LOOP
3 DBMS_OUTPUT.PUT_LINE('呼び出されます(1-1)');
4 IF (1=1) THEN
5 EXIT ;
6 END IF;
7 DBMS_OUTPUT.PUT_LINE('呼び出されません(1)');
8 END LOOP;
9 DBMS_OUTPUT.PUT_LINE('呼び出されます(1-2)');
10 END;
11 /
呼び出されます(1-1)
呼び出されます(1-2)
PL/SQLプロシージャが正常に完了しました。
EXIT WHEN 使用によるループ処理の脱出
SQL> BEGIN
2 LOOP
3 DBMS_OUTPUT.PUT_LINE('呼び出されます(2-1)');
4 EXIT WHEN (1=1) ;
5 DBMS_OUTPUT.PUT_LINE('呼び出されません(2)');
6 END LOOP;
7 DBMS_OUTPUT.PUT_LINE('呼び出されます(2-2)');
8 END;
9 /
呼び出されます(2-1)
呼び出されます(2-2)
PL/SQLプロシージャが正常に完了しました。
条件式の 1=0 や 1=1 は SQL において真、偽をあらわすときに良く用いられる式である。 この例は PL/SQL であるので、単に TRUE を使用するほうが自然だとは思う。
SQL には PL/SQL のようにブーリアン型が存在しない(※)ため、直接 TRUE, FALSE を SQL 式として使用することできない。
そのため、しばしば、このような表現を用いることがある。
(※) 標準 SQL においてブーリアンを使用することができるが Oracle 10g 時点ではサポートされていない。
PL/SQLのループ処理に関する内容