MySQL の WHILE 文
ここでは MySQL の WHILE 文についてご説明します。
MySQL の WHILE 文の使い方
MySQL では、ストーアドプログラム内のフロー制御で WHILE 文を使って、指定した条件が True を返す間、繰り返しステートメントを実行することができます。
WHILE 文の基本的な構文は次の通りです。
[開始ラベル:] WHILE 条件文 DO
繰り返したいステートメント
END WHILE [終了ラベル];
条件文が True の間、「繰り返したいステートメント」を繰り返し実行します。
条件文のチェックは最初に行われるので、条件文が最初から False になる時は 「繰り返したいステートメント」は一度も実行されません。
開始と終了ラベルはオプショナルですが、つける場合は同じラベル名でなくてはならず、後でご説明する LEAVE 文や ITERATE 文で使います。
それでは、WHILE 文を実際に使ってみましょう。
今回は WHILE 文を使って、引数として渡した start_idx から end_idx までの数をカンマでつなげるだけの簡単なストアードプロシージャを作ります。
DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test (start_idx INT, end_idx INT)
BEGIN
DECLARE result VARCHAR(500) DEFAULT '';
WHILE start_idx <= end_idx DO
SET result = CONCAT(result, start_idx, ',');
SET start_idx = start_idx + 1;
END WHILE;
IF CHAR_LENGTH(result) > 1 THEN
SET result = LEFT(result, CHAR_LENGTH(result) - 1);
END IF;
SELECT result;
END//
DELIMITER ;
8 行目~11 行目で WHILE 文を使っています。
start_idx <= end_idx が true の間、DO と END WHILE の間の 9 行目と 10 行目のステートメントが実行されます。
9 行目では result という変数に start_idx とカンマを追加しています。
10 行目では start_idx に 1 を足しています。
13 ~ 15 行目は result の一番後ろのカンマを取り除いているだけです。
このストアードプロシージャを作成して、start_idx = 1、end_idx = 10 で実行すると次のようになります。
CALL test(1, 10);
[実行結果]
result に 1,2,3,4,5,6,7,8,9,10 が入っていて、10 回ループされたことがわかります。
MySQL の WHILE 文で BREAK する (LEAVE)
MySQL で WHILE 文の途中でループを抜けたい(BREAK したい)時には、LEAVE 文を使って抜けることができます。
DO と END WHILE の間の繰り返したいステートメントの中で、LEAVE ラベル名; のように指定します。
ラベル名: WHILE 条件文 DO
...
LEAVE ラベル名;
...
END WHILE ラベル名
例えば、ループ中に result の文字の長さが 5 以上になったらループを抜けたいのであれば、次のようにできます。
DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test (start_idx INT, end_idx INT)
BEGIN
DECLARE result VARCHAR(500) DEFAULT '';
while_loop1: WHILE start_idx <= end_idx DO
SET result = CONCAT(result, start_idx, ',');
IF CHAR_LENGTH(result) >= 5 THEN
LEAVE while_loop1;
END IF;
SET start_idx = start_idx + 1;
END WHILE while_loop1;
IF CHAR_LENGTH(result) > 1 THEN
SET result = LEFT(result, CHAR_LENGTH(result) - 1);
END IF;
SELECT result;
END//
DELIMITER ;
8 行目の WHILE の前に開始ラベルの while_loop1: を、14 行目の END WHILE の後に終了ラベルの while_loop1 を追加します。
10 ~ 12 行目で result の文字数をチェックし、5 以上であれば LEAVE while_loop1; でループを抜けています。
このクエリーを実行して test ストアードプロシージャを再生成し、start_idx = 1、end_idx = 10 で実行すると次のようになります。
CALL test(1, 10);
[実行結果]
result には 1,2,3 のみが入っていて、result の文字数が 5 以上になった時にループを抜けているのがわかります。
MySQL の WHILE 文で CONTINUE する (ITERATE)
MySQL で WHILE 文の途中で、その後のステートメントをスキップしてループの実行を続けたい(CONTINUE したい)時には、ITERATE 文を使って行うことができます。
ITERATE 文は ITERATE ラベル名; のように使い、指定したラベルのループを最初から実行します。
ラベル名: WHILE 条件文 DO
...
ITERATE ラベル名;
...
END WHILE ラベル名
例えば、ITERATE 文を使って、start_idx が奇数の時のみ result に文字列を追加したいのであれば、次のようにできます。
DROP PROCEDURE IF EXISTS test;
DELIMITER //
CREATE PROCEDURE test (start_idx INT, end_idx INT)
BEGIN
DECLARE result VARCHAR(500) DEFAULT '';
while_loop1: WHILE start_idx <= end_idx DO
IF start_idx % 2 = 0 THEN
SET start_idx = start_idx + 1;
ITERATE while_loop1;
END IF;
SET result = CONCAT(result, start_idx, ',');
SET start_idx = start_idx + 1;
END WHILE while_loop1;
IF CHAR_LENGTH(result) > 1 THEN
SET result = LEFT(result, CHAR_LENGTH(result) - 1);
END IF;
SELECT result;
END//
DELIMITER ;
9 ~ 12 行目で start_idx を 2 で割った余りが 0 の時は start_idx に 1 を足してから、ITERATE while_loop1; でループの最初から実行するようにしています。
ここで ITERATE 文の前に start_idx に 1 を足すのを忘れると、WHILE の条件文がずっと True になり、無限ループになってしまうのでお気をつけくださいね。
このクエリーを実行して test ストアードプロシージャを再生成し、start_idx = 1、end_idx = 10 で実行すると次のようになります。
CALL test(1, 10);
[実行結果]
result には 1,3,5,7,9 が入っていて、偶数の時は ITERATE 文以降のステートメントが実行されずに、ループが継続されているのがわかります。
以上、MySQL の WHILE 文についてご説明しました。