web-dev-qa-db-ja.com

MySQLでの結果セットのループ

MySQLでストアドプロシージャを記述して、多少単純な選択クエリを実行し、結果をループして、追加のクエリ、データ変換を実行するか、データを完全に破棄するかを決定しようとしています。事実上、私はこれを実装したい:

$result = mysql_query("SELECT something FROM somewhere WHERE some stuff");
while ($row = mysql_fetch_assoc($result)) {
    // check values of certain fields, decide to perform more queries, or not
    // tack it all into the returning result set
}

ただ、MySQLでのみ必要なので、プロシージャとして呼び出すことができます。トリガーにはFOR EACH ROW ...構文があることを知っていますが、CREATE TRIGGER ...構文以外で使用するためのこのような記述は見つかりません。 MySQLのループメカニズムのいくつかを読みましたが、これまでのところ、次のようなものを実装することしか想像できません。

SET @S = 1;
LOOP
    SELECT * FROM somewhere WHERE some_conditions LIMIT @S, 1
    -- IF NO RESULTS THEN
    LEAVE
    -- DO SOMETHING
    SET @S = @S + 1;
END LOOP

これでさえ私の頭の中ではややかすんでいますが。

参考までに、必ずしも関連するとは思いませんが、最初のクエリは4つのテーブルを結合して階層型のアクセス許可のモデルを形成し、特定のアクセス許可のチェーンの高さに基づいて、追加の情報を取得しますその許可を継承する子。

54
Dereleased

このような何かがトリックを行う必要があります(ただし、詳細については、スニペットの後に読んでください)

CREATE PROCEDURE GetFilteredData()
BEGIN
  DECLARE bDone INT;

  DECLARE var1 CHAR(16);    -- or approriate type
  DECLARE Var2 INT;
  DECLARE Var3 VARCHAR(50);

  DECLARE curs CURSOR FOR  SELECT something FROM somewhere WHERE some stuff;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

  DROP TEMPORARY TABLE IF EXISTS tblResults;
  CREATE TEMPORARY TABLE IF NOT EXISTS tblResults  (
    --Fld1 type,
    --Fld2 type,
    --...
  );

  OPEN curs;

  SET bDone = 0;
  REPEAT
    FETCH curs INTO var1,, b;

    IF whatever_filtering_desired
       -- here for whatever_transformation_may_be_desired
       INSERT INTO tblResults VALUES (var1, var2, var3 ...);
    END IF;
  UNTIL bDone END REPEAT;

  CLOSE curs;
  SELECT * FROM tblResults;
END

考慮すべきいくつかのこと...

上記のスニペットについて:

  • クエリの一部、特に検索条件をストアドプロシージャに渡して、汎用性を高めたい場合があります。
  • このメソッドが複数のセッションなどによって呼び出される場合、並べ替えのセッションIDを渡して一意の一時テーブル名を作成する場合があります(異なるセッションは同じ一時ファイルの名前空間を共有しないため、実際には不必要な懸念です。以下のGruberのコメントを参照してください) )
  • 変数宣言、SELECTクエリなど、いくつかの部分を適切に指定する必要があります

より一般的には、カーソルの必要性を回避しようとする

カーソルは祝福が混在しているため、意図的にカーソル変数curs [e]に名前を付けました。 SQLの宣言型では表現が難しいかもしれない複雑なビジネスルールを実装するのに役立ちますが、SQLの手続き型(命令型)を使用するようになります。表現力があり、プログラミングの面で、多くの場合、パフォーマンスの面で非効率的です。

「プレーン」(宣言的)SQLクエリのコンテキストで必要な変換とフィルタリングを表現することを検討できます。

74
mjv

カーソルを使用します。

カーソルは、ドキュメントを読むときのバッファ付きリーダーのように考えることができます。各行をドキュメント内の行と考える場合、次の行を読み、操作を実行してからカーソルを進めます。

4
AlishahNovin