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=01=1 は SQL において真、偽をあらわすときに良く用いられる式である。 この例は PL/SQL であるので、単に TRUE を使用するほうが自然だとは思う。 SQL には PL/SQL のようにブーリアン型が存在しない(※)ため、直接 TRUE, FALSE を SQL 式として使用することできない。 そのため、しばしば、このような表現を用いることがある。

(※) 標準 SQL においてブーリアンを使用することができるが Oracle 10g 時点ではサポートされていない。



PL/SQLのループ処理に関する内容

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)