1. ホーム
  2. mysql

[解決済み] テーブルのすべての行をループするにはどうしたらいいですか?(MySQL)

2022-10-09 13:07:36

質問

Aというテーブルがあり、主キーIDが1つあります。

今、私はAのすべての行を通過したい。

Aの各レコードのために'のようなものを見つけましたが、これはMySQLでそれを行う方法ではないようです。

私は各行ごとにフィールドを取り、それを変換し、別のテーブルに挿入し、そして行のフィールドのいくつかを更新したいのですが、それは可能ですか?選択部分と挿入を1つのステートメントに入れることができますが、同様にそこに更新を取得する方法がわかりません。だからループさせたいんです。そして、練習のために、私はMySQL以外のものを使いたくありません。

編集

例を教えていただきたいのですが。

また、プロシージャに入れる必要のない解決策を。

編集2

OK このシナリオを考えてみてください。

テーブルAとB、それぞれにフィールドIDおよびVALがあります。

さて、これが私がやりたいことの擬似コードです。

for(each row in A as rowA)
{
  insert into B(ID, VAL) values(rowA[ID], rowA[VAL]);
}

は、基本的にループを使ってAの内容をBにコピーしています。

(これは単純化した例で、もちろんこのためにループを使うことはないでしょう) }

どのように解決するのですか?

ループの提案は、プロシージャタイプのソリューションのための要求を意味するので。以下は私のものです。

テーブルから取り出した単一のレコードで動作する任意のクエリは、このようにテーブルの各行を通して実行させるためにプロシージャでラップすることができます。

まず、同じ名前の既存のプロシージャを削除し、プロシージャを書こうとしているときに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();

あなたのリクエスト例からコピーした "INSERT INTO" の行で好きなことを何でもすることができます。

ここで使用されている "INSERT INTO" 行は、質問の中の行を反映していることに注意してください。この回答に対するコメントのように、実行中のSQLのどのバージョンであっても、あなたのクエリが構文的に正しいことを確認する必要があります。

IDフィールドがインクリメントされ、1から始まる単純なケースでは、例の行は次のようになる可能性があります。

INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;

SELECT COUNT"の行を以下のように置き換えます。

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;
;;

使用する変数は、問い合わせたテーブルの変数と同じ型として宣言することを忘れないようにしましょう。

私のアドバイスは、できる限りセットベースのクエリを使用し、必要な場合にのみ単純なループやカーソルを使用することです。