ループの提案は、プロシージャタイプのソリューションの要求を意味するためです。これが私のものです。
テーブルから取得した単一のレコードで機能するクエリは、次のようにテーブルの各行を実行するようにプロシージャでラップできます。
まず、同じ名前の既存のプロシージャをすべて削除し、区切り文字を変更して、プロシージャを記述しようとしているときにSQLが各行を実行しようとしないようにします。
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
次に、例に従って手順を示します(わかりやすくするためにtable_Aとtable_Bを使用)
CREATE PROCEDURE ROWPERROW()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM table_A INTO n;
SET i=0;
WHILE i<n DO
INSERT INTO table_B(ID, VAL) SELECT (ID, VAL) FROM table_A LIMIT i,1;
SET i = i + 1;
END WHILE;
End;
;;
次に、区切り文字をリセットすることを忘れないでください
DELIMITER ;
そして、新しい手順を実行します
CALL ROWPERROW();
サンプルリクエストからコピーした「INSERTINTO」行で、好きなことを行うことができます。
ここで使用されている「INSERTINTO」行は、質問の行を反映していることに注意してください。この回答へのコメントに従って、実行しているSQLのバージョンに対してクエリが構文的に正しいことを確認する必要があります。
IDフィールドがインクリメントされ、1から始まる単純なケースでは、例の行は次のようになります。
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
「SELECTCOUNT」行を
に置き換えますSET n=10;
table_Aの最初の10レコードでのみクエリをテストできます。
最後に一つだけ。このプロセスは、さまざまなテーブル間でネストするのも非常に簡単で、親テーブルの各行から新しいテーブルにさまざまな数のレコードを動的に挿入する1つのテーブルでプロセスを実行できる唯一の方法でした。
より高速に実行する必要がある場合は、必ずセットベースにするようにしてください。そうでない場合は、これで問題ありません。上記をカーソル形式で書き直すこともできますが、パフォーマンスが向上しない場合があります。例:
DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
DELIMITER ;;
CREATE PROCEDURE cursor_ROWPERROW()
BEGIN
DECLARE cursor_ID INT;
DECLARE cursor_VAL VARCHAR;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_i CURSOR FOR SELECT ID,VAL FROM table_A;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO cursor_ID, cursor_VAL;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO table_B(ID, VAL) VALUES(cursor_ID, cursor_VAL);
END LOOP;
CLOSE cursor_i;
END;
;;
使用する変数は、クエリされたテーブルの変数と同じ型として宣言することを忘れないでください。
可能な場合はセットベースのクエリを使用し、必要な場合にのみ単純なループまたはカーソルを使用することをお勧めします。