データベース開発にPHPのPDO(PHPデータオブジェクト)を使用する場合、 PDostatement :: RowCount()は、特に更新、削除、その他のステートメントを実行した後、クエリの影響を受ける行の数を取得するためによく使用されます。ただし、一部のシナリオでは、そのリターン結果は「誤解を招く」、またはバギーを感じることがあります。
この記事では、 RowCount()が私たちが予想したとおりではない理由を深く掘り下げ、その背後にある理由を明らかにし、それに対処するための正しい方法を与えます。
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
$stmt->execute([':id' => 123]);
echo $stmt->rowCount(); // 削除された行の数を出力します
このコードでは、レコードを削除し、いくつかのレコードが影響を受けることをrowcount()を通じて知りたいと考えています。これは通常、削除および更新ステートメントで正常に機能します。ただし、選択したステートメントまたはいくつかの特別な状況が関係すると、問題が発生します。
rowcount()は、postgreSQLなどの一部のデータベースによって選択されたクエリに対してサポートされていますが、 mysqlでselect後にrowcount()を呼び出すと通常0が返されます。その理由は、PDOがMySQLでデフォルトでMySQL_ATTR_USE_BUFFERED_QUERYを使用しているためです。行は遅れて抽出され、rowCountは行数を正確に知ることができません。
$stmt = $pdo->query("SELECT * FROM users");
echo $stmt->rowCount(); // 存在する MySQL 可能な出力 0
ステートメントが法的に実行されていても、データベースに実際の変更がない限り、 rowcount()が0を返します。たとえば、:
$stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id");
$stmt->execute([':name' => 'Alice', ':id' => 123]);
echo $stmt->rowCount(); // もし name すでに Alice,その後、返します 0
これはエラーではありませんが、SQLの機能です。実際の変更がなければ、ラインに「影響」としてカウントされません。
さまざまなデータベースドライバーの実装は、rowCount()を一貫性のないものにサポートしています。例えば:
mysql: selectは正しい値を返さず、更新/削除をサポートします。
PostgreSQL:ほとんどのステートメントはそれをサポートしています。
sqlite:ほとんどのステートメントはそれをサポートしています。
Oracle:動作はより複雑で、注意して使用する必要があります。
$stmt = $pdo->query("SELECT * FROM users WHERE status = 'active'");
$rows = $stmt->fetchAll();
echo count($rows);
またはトラバーサルを使用します。
$count = 0;
foreach ($stmt as $row) {
$count++;
}
echo $count;
$stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id AND name != :name");
$stmt->execute([':name' => 'Alice', ':id' => 123]);
echo $stmt->rowCount(); // ときだけ name 実際の変更に戻ります 1
多くの場合、特にクエリまたはバッチ操作では、SQLが影響を受ける行の数を直接返すことをお勧めします。
$stmt = $pdo->query("SELECT COUNT(*) FROM users WHERE status = 'active'");
$count = $stmt->fetchColumn();
echo $count;
すべてのドライバーが一貫して振る舞うと仮定しないでください。次の方法を使用して、PDOを初期化するときに互換性を検出または設定できます。
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password', [
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
]);
pdostatement :: rowcount()は一般的に使用されるインターフェイスですが、さまざまなデータベースや異なるSQLタイプで希望どおりに機能するとは限りません。開発者として、その範囲と制限を理解することは、落とし穴を避けるための鍵です。
最も安全な戦略は次のとおりです。
選択したクエリのrowcount()に依存しないでください。
更新/削除などの操作の場合、「行に影響する」は「行を見つける」ではないことが理解されています。
正確な制御または横断段階の互換性については、SQLレベルのカウントロジックの使用を検討してください。