在使用PHP 的PDO(PHP Data Objects)進行數據庫操作時, PDO::errorCode()方法返回'00000'表示當前沒有錯誤發生。這似乎意味著數據庫操作成功完成,但實際上, errorCode返回'00000'並不總是能準確反映操作是否真正成功。
本文將詳細講解為什麼PDO::errorCode()返回'00000'並不能完全代表操作成功,並介紹幾種更可靠的方法來判斷數據庫操作是否真正成功。
PDO::errorCode()返回的'00000'是一個SQLSTATE 標準碼,表示“無錯誤”。它主要反映數據庫通信過程中是否出現了錯誤,如語法錯誤、連接失敗等。
但有些情況下,即使執行了SQL 語句,沒有發生錯誤, errorCode()仍返回'00000' ,但操作結果可能並非理想狀態。例如:
執行了UPDATE語句,但沒有任何行被實際更新(因為條件未匹配任何記錄)。
執行了DELETE語句,但沒有行被刪除。
執行了插入語句,但數據被觸發器修改或約束條件未生效。
這些情況不會導致錯誤,但對業務邏輯來說,操作未成功生效。
PDOStatement::rowCount()返回最近一次執行的SQL 語句所影響的行數。它是判斷UPDATE 、 DELETE是否真正改變數據的重要依據。
<?php
$pdo = new PDO('mysql:host=m66.net;dbname=testdb;charset=utf8', 'username', 'password');
$sql = "UPDATE users SET status = 1 WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([':id' => 123]);
if ($stmt->errorCode() === '00000') {
$affectedRows = $stmt->rowCount();
if ($affectedRows > 0) {
echo "更新成功,影響了 {$affectedRows} 行。";
} else {
echo "執行成功,但沒有行被更新。";
}
} else {
echo "數據庫操作發生錯誤,錯誤碼:" . $stmt->errorCode();
}
?>
這裡,雖然errorCode()是'00000' ,但只有rowCount()大於零才算真正修改了數據。
對自增主鍵的插入操作,可以通過PDO::lastInsertId()獲取插入的記錄ID。如果返回非空且合理的ID,說明插入成功。
<?php
$pdo = new PDO('mysql:host=m66.net;dbname=testdb;charset=utf8', 'username', 'password');
$sql = "INSERT INTO users (name, email) VALUES (:name, :email)";
$stmt = $pdo->prepare($sql);
$stmt->execute([':name' => '張三', ':email' => 'zhangsan@example.com']);
if ($stmt->errorCode() === '00000') {
$lastId = $pdo->lastInsertId();
if ($lastId) {
echo "插入成功,新的用戶ID為:{$lastId}";
} else {
echo "執行成功,但未返回新的插入ID。";
}
} else {
echo "數據庫操作發生錯誤,錯誤碼:" . $stmt->errorCode();
}
?>
注意, lastInsertId()依賴數據庫表主鍵為自增,否則返回值可能為空。
在執行多條操作或複雜操作時,開啟事務並捕獲異常是最安全的方式,可以確保操作原子性。
<?php
try {
$pdo = new PDO('mysql:host=m66.net;dbname=testdb;charset=utf8', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$sql1 = "UPDATE accounts SET balance = balance - 100 WHERE user_id = :user_id";
$stmt1 = $pdo->prepare($sql1);
$stmt1->execute([':user_id' => 1]);
if ($stmt1->rowCount() === 0) {
throw new Exception("賬戶扣款失敗,無受影響行數");
}
$sql2 = "UPDATE accounts SET balance = balance + 100 WHERE user_id = :user_id";
$stmt2 = $pdo->prepare($sql2);
$stmt2->execute([':user_id' => 2]);
if ($stmt2->rowCount() === 0) {
throw new Exception("賬戶充值失敗,無受影響行數");
}
$pdo->commit();
echo "轉賬成功";
} catch (Exception $e) {
$pdo->rollBack();
echo "操作失敗,原因:" . $e->getMessage();
}
?>
這裡,任何一個操作無效都會拋出異常,回滾事務,避免數據不一致。
PDO::errorCode()返回'00000'表示無錯誤,但不代表操作有實際效果。
結合PDOStatement::rowCount()判斷影響行數,是判斷修改類操作是否真正生效的關鍵。
對插入操作,使用PDO::lastInsertId()來確認插入成功與否。
複雜操作建議使用事務和異常捕獲,保證數據操作的完整性和準確性。
通過以上方法,可以更準確地判斷數據庫操作是否真正成功,避免因僅依賴errorCode()帶來的邏輯漏洞。