2

したがって、PDO MySQL を使用する際に発生する障害は、次のようなクエリを実行した場合です。

$db->pquery("SELECT `category_id`, `category_name` FROM `database_categorys` ORDER BY `category_name` ASC");
while ($category = $db->fetch())
{
}

while ループ内では、別のクエリを実行できないか、前のクエリがキャンセルされます。それを回避する方法はありますか?

これは私のpqueryです:

// A plain query
public function pquery($sql)
{
    $this->STH = $this->database->prepare($sql);  

    $this->counter++;

    return $this->STH->execute();
}

そして私のフェッチ機能:

public function fetch()
{
    $this->STH->setFetchMode(PDO::FETCH_ASSOC); 
    return $this->STH->fetch();
}
4

2 に答える 2

4

これは PDO の制限ではなく、MySQL クライアント ライブラリの制限です。MySQL は、一度に 1 つの進行中のクエリのみをサポートします。最初のクエリがまだ開いているカーソルを持っている間 (つまり、返す結果がまだある場合)、別のクエリを実行することはできません。

次のオプションがあります。

  • PDOStatement::fetchAll()を使用して、外側のクエリの結果セット全体を PHP 配列に収集します。これで、外側のクエリのクエリ結果が完成します。次に、配列をループして、ループの反復ごとに追加の SQL クエリを実行できます。

    ただし、外側の結果セットのループ反復ごとに新しいクエリを実行するのは効率的ではありません。これは、アプリケーションのパフォーマンスを低下させる良い方法です。

    これをN+1 選択問題と呼ぶ人もいます。最初の選択を実行すると N 行が返され、次に最初の選択の結果に基づいて N 選択を実行するからです。

  • MySQL を使用する場合は、基本的に同じことを行うPDO::MYSQL_ATTR_USE_BUFFERED_QUERYを使用し、すべての行をダウンロードして内部的に配列に保存します。fetch()次に、バッファリングされた結果を反復処理する ための後続の呼び出し。

    しかし、これには N+1 Selects アンチパターンも含まれます。

  • 必要な値を取得する単一の SQL クエリを作成することをお勧めします。コメントから推測すると、カテゴリと、category_id が一致する別のテーブルからの関連する行の数が必要です。このような SQL クエリの例を次に示します。

    $db->pquery("SELECT c.`category_id`, c.`category_name`, COUNT(*) AS `count`
    FROM `database_categorys` AS c 
    LEFT OUTER JOIN `other_table` AS t ON t.category_id = c.category_id
    GROUP BY c.category_id
    ORDER BY c.`category_name` ASC");
    

結合は、SQL の基本的な部分です。結合の使い方を学ばずに SQL を使おうとするのは、whileループの使い方を学ばずに PHP を使うようなものです。

ここから始めてください: SQL 結合の視覚的な説明.

于 2012-11-02T20:28:32.273 に答える
0

最初のクエリwhile loop or fetching of recordsが完了したら、2 番目のクエリを実行してみてください。

編集:

JOINそのために使用するか、 を使用して 2 つのクエリを組み合わせる必要がありますINマニュアルはこちら

于 2012-11-02T20:05:09.863 に答える