在使用PHP 的PDO(PHP Data Objects)擴展進行數據庫操作時, PDOStatement::rowCount()方法常被用來判斷受影響的行數。尤其是在與prepared statements(預處理語句)一起使用時,正確地使用rowCount()是確保應用邏輯嚴謹的重要環節。本文將介紹在這種場景下使用rowCount()的最佳實踐,並指出一些常見的誤區。
rowCount()方法用於返回上一次執行SQL 語句所影響的行數。在不同類型的SQL 操作中,其行為略有差異:
對於INSERT 、 UPDATE和DELETE語句: rowCount()返回受影響的行數。
對於SELECT語句:並不是所有數據庫驅動都支持返回行數;在某些驅動(如MySQL)下返回值不可靠。
許多開發者嘗試在SELECT查詢後使用rowCount()來獲取結果數量:
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = ?");
$stmt->execute(['active']);
$count = $stmt->rowCount(); // 可能並不返回預期值
這是不推薦的做法。對於SELECT查詢,更安全可靠的方法是:
$rows = $stmt->fetchAll();
$count = count($rows);
這樣才能確保你真正獲得了返回的數據數量。
rowCount()的行為是數據庫驅動依賴的。例如,在PostgreSQL 中, rowCount()對SELECT是有效的,而在MySQL 中則不一定。開發時需要根據目標數據庫做兼容處理。
$pdo = new PDO("mysql:host=localhost;dbname=example", "user", "password");
$stmt = $pdo->prepare("UPDATE products SET price = ? WHERE id = ?");
$stmt->execute([99.99, 42]);
if ($stmt->rowCount() > 0) {
echo "更新成功,受影響的行數:" . $stmt->rowCount();
} else {
echo "未更新任何數據。";
}
$stmt = $pdo->prepare("DELETE FROM sessions WHERE last_active < NOW() - INTERVAL 30 DAY");
$stmt->execute();
if ($stmt->rowCount() > 0) {
echo "清理了 " . $stmt->rowCount() . " 個過期會話。";
} else {
echo "沒有會話需要清理。";
}
有時你的SQL 執行成功,但rowCount()返回0 —— 這通常意味著操作沒有改變任何行。例如,一條UPDATE語句試圖將某列的值設置為相同的值,這種情況下行不會被視為“受影響”。
可以通過啟用SQL 日誌或者使用類似如下方式輔助調試:
$stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id");
$stmt->execute(['name' => 'Alice', 'id' => 10]);
echo "SQL 執行成功,受影響行數:" . $stmt->rowCount();
與rowCount()無關但相關的是,始終建議:
使用綁定參數( ?或命名參數)防止SQL 注入;
捕獲PDOException處理錯誤;
設置合適的PDO 錯誤模式:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
為了更好地管理項目中的數據操作,建議採用統一的數據抽象層,並在必要時加入日誌機制。例如:
// 假設你有一個日誌系統 URL
$logUrl = "https://gitbox.net/logs/db-activity";
你可以在執行關鍵操作時將受影響行數和SQL 語句內容髮送到該接口進行監控,前提是你控制該域名和接口安全。