Oracle Database の新機能には大規模環境に対応するばかりではなく、プログラミングに関する細かい仕様の追加も含まれます。Oracle Database 21c では何十年も使われてきた PL/SQL の FOR LOOP 構文に新しいイテレータ構文が追加されました。
複数イテレーター
FOR LOOP 文に複数のイテレーターをカンマ(,)で区切って指定できます。最初のイテレーターが完了すると、次のイテレーターが開始されます。複数のイテレーター内の値が重なっていても問題ありません。
下記の例ではイテランドの値を 1~3 と 5~7 の2つ指定しています。
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 FOR i IN 1 .. 3, 5 .. 7 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
2
3
5
6
7
PL/SQLプロシージャが正常に完了しました。
逆順
イテレーターの値を逆順に出力する際には REVERSE 句を指定します。「REVERSE 5 .. 1」と記述してしまうと、ループに入らずに終了してしまいます。下記の例では 1~5 の値を逆順に指定しています。
SQL> BEGIN
2 FOR i IN REVERSE 1 .. 5 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
5
4
3
2
1
PL/SQLプロシージャが正常に完了しました。
SQL> BEGIN
2 FOR i IN REVERSE 5 .. 1 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
PL/SQLプロシージャが正常に完了しました。
ステッピング
デフォルトでは FOR LOOP で指定する数値(イテランド)は「1」ずつ増加して上限まで増加します。
「BY」句に値を指定することで増分を変化させることができます。ただし BY 句に小数点を指定しただけだと整数に丸められるため、小数点を許容するデータ型を指定します。下記の例では最初に BY 句だけ指定しましたが、ループは3回で終わっています。次にデータ型としてNUMBER(5, 1)を指定し、0.5ずつイテランドを増加し、ループを6回実行しています。
SQL> BEGIN
2 FOR i IN 1 .. 3 BY 0.5 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
2
3
PL/SQLプロシージャが正常に完了しました。
SQL> BEGIN
2 FOR i NUMBER(5, 1) IN 1 .. 3 BY 0.5 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
1.5
2
2.5
3
PL/SQLプロシージャが正常に完了しました。
実行条件指定
LOOP 文に WHEN句を指定すると条件に合致した場合だけループが実行されます。下記の例では条件「MOD(i, 2) = 0」が真になる場合だけループが実行されています。
SQL> BEGIN
2 FOR i IN 1 .. 10 WHEN MOD(i, 2) = 0 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
2
4
6
8
10
PL/SQLプロシージャが正常に完了しました。
終了条件指定
LOOP 文に WHILE 句を指定すると、条件に一致しなくなったらループを終了します。FOR LOOP にする必要は無い気がしますが、構文としては有効です。
SQL> BEGIN
2 FOR i IN 1 .. 10 WHILE i <= 5 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
2
3
4
5
PL/SQLプロシージャが正常に完了しました。
組み合わせ
上記に記載した機能は複数を組み合わせて記述できます。下記の例では複数のイテレーターと、REVERSE句、BY句を指定しています。
SQL> BEGIN
2 FOR i FLOAT IN 1 .. 3, REVERSE 5 .. 7 BY 0.5 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
2
3
7
6.5
6
5.5
5
PL/SQLプロシージャが正常に完了しました。