行フェッチの試行が失敗するまでフェッチする必要があります。結果セットに行が1つしかない場合があり、フェッチは1つで十分だと思いますが、そうではありません(バッファーなしのクエリを使用している場合)。 PDOは、最後に到達して次の行をフェッチしようとするまで、行数を認識しませんが、失敗します。
「フェッチが失敗するまでフェッチ」しなかった他のステートメントがある可能性があります。はい、1つのフェッチが失敗するまでフェッチしているようです。 のステートメントですが、それはあなたがそれらすべてのためにそれをしたという意味ではありません。
明確にするために-execute()を介してクエリを実行する場合、dbからphpにフェッチする必要がある結果セットを作成します。 PDOは、一度に(接続ごとに)これらの「フェッチ中の結果セット」の1つのみを処理できます。 execute()の別の呼び出しから別の結果セットのフェッチを開始する前に、結果セットを最後まで完全にフェッチする必要があります。
「fetch()が失敗するまでfetch()を呼び出す」と、結果がなくなったためにfetch()の最後の呼び出しが失敗したときに、結果の最後に到達したという事実がPDOによって内部的に記録されます。 PDOは、結果が完全にフェッチされたことに満足し、その結果セット用に確立されたphpとdbの間の内部リソースをクリーンアップして、他のクエリを作成/フェッチできるようにします。
PDOを「fetch()が失敗するまでfetch()を呼び出す」ようにする方法は他にもあります。
- fetchAll()を使用するだけです。これは、すべての行をフェッチするだけなので、結果セットの最後に到達します。
- または単にcloseCursor()を呼び出す
* closeCursor()のソースを見ると、デフォルトの実装は文字通り行をフェッチし、最後に到達するまでそれらを破棄します。明らかにcで書かれていますが、多かれ少なかれこれを行います:
function closeCursor() {
while ($row = $stmt->fetch()) {}
$this->stmtFullyFetched = true;
}
一部のdbドライバーは、誰も気にしない多くの行をフェッチする必要がない、より効率的な実装を備えている場合がありますが、これがPDOが行うデフォルトの方法です。とにかく...
通常、バッファリングされたクエリを使用する場合、これらの問題は発生しません。その理由は、バッファリングされたクエリでは、実行直後にPDOが自動的にdbの結果をphpメモリに完全にフェッチするため、「fetch()が失敗するまでfetch()を呼び出す」部分が自動的に実行されるためです。後でfetch()またはfetchAll()を自分で呼び出すと、dbからではなくphpメモリから結果がフェッチされます。したがって、基本的に、バッファリングされたクエリを使用すると、結果セットはすぐに完全にフェッチされます。したがって、同時に複数の「フェッチ中の結果セット」を持つ機会はありません(phpはシングルスレッドであるため、2つのクエリが発生する可能性はありません)。同時に実行しています。
これを考えると:
$sql = "select * from test.a limit 1";
$stmt = $dbh->prepare($sql);
$stmt->execute(array());
結果セットを完全にフェッチする方法(最初の行のみが必要であると想定):
$row = $stmt->fetch();
$stmt->closeCursor();
または
list($row) = $stmt->fetchAll(); //tricky
または
$row = $stmt->fetch();
while ($stmt->fetch()) {}