PHPのデータベース抽象化レイヤーPDO(PHPデータオブジェクト)では、 pdostatement :: rowcount()は、最後のSQL実行の影響を受ける行数を返す一般的な方法です。ただし、多くの開発者は、さまざまなデータベースドライバーで使用する場合、メソッドの動作が一貫していないことに気付くでしょう。また、いくつかのシナリオで期待される結果を取得できません。
公式のPHPドキュメントの指示によると:
ほとんどのデータベースでは、 rowCount()はステートメントの削除、挿入、または更新にのみ適用されます。選択されたステートメントの場合、一部のデータベースドライバーは影響を受ける行の数を返す場合がありますが、これは統一されたPDO動作の一部ではありません。
つまり、 rowCount()の動作は、基礎となるデータベースドライバーの実装に依存します。
データベースタイプ | 選択されたステートメントのRowCountをサポートします | 更新/削除/挿入のためにRowCountをサポートします |
---|---|---|
mysql | ?信頼できない(通常0を返す) | ?影響を受ける行の数を返します |
postgreSql | ?サポート | ?サポート |
sqlite | ?サポート | ?サポート |
MSSQL | ? (依存関係ドライバーの実装) | ? |
たとえば、mysqlで:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query("SELECT * FROM users");
echo $stmt->rowCount(); // 通常は返されます 0
ただし、PostgreSQLまたはSQLiteでは、実際の行数が返される場合があります。
主な理由は、データベースドライバーがさまざまな方法で、特に選択のためにSQLを実行することです。一部のドライバーは、すべての結果を事前にロードするのではなく、代わりに移動中にデータを取得します。この場合、事前にいくつの行があるかがわかりません。
公式のMySQLドライバー( MySQLND )は、 SELECTの場合、 rowCount()は依存しないでください。
$stmt = $pdo->query("SELECT * FROM users");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$count = count($rows);
echo "一般 {$count} ラインデータ";
または:
$count = 0;
$stmt = $pdo->query("SELECT * FROM users");
while ($row = $stmt->fetch()) {
$count++;
}
echo "一般 {$count} ラインデータ";
注:データボリュームが大きい場合、 fetchall()は多くのメモリを占有し、ループカウントを使用することをお勧めします。
$stmt = $pdo->prepare("UPDATE users SET status = 'active' WHERE last_login > NOW() - INTERVAL 7 DAY");
$stmt->execute();
echo "更新 " . $stmt->rowCount() . " わかりました";
そのような操作のrowcount()は通常信頼できます。
独自のRowCount関数をカプセル化し、SQLタイプを判断し、適切な統計的方法を選択できます。
function safeRowCount(PDOStatement $stmt, $sqlType = 'SELECT') {
if (strtoupper($sqlType) === 'SELECT') {
return count($stmt->fetchAll());
} else {
return $stmt->rowCount();
}
}
これにより、さまざまなデータベースドライバーで動作を一貫させることができます。
pdostatement :: RowCount()の一貫性のない動作は、PHPデータベース開発における一般的な落とし穴の1つです。その基礎となるメカニズムを理解し、SQLタイプに基づいて適切な処理方法を選択することは、互換性の高いコードを作成する鍵です。
より多くのサンプルコードまたは共有エクスペリエンスについては、当社のテクノロジーコミュニティhttps://gitbox.net/forumをご覧ください。