在使用PHP 的MySQLi 擴展進行數據庫操作時, UPDATE語句是最常用的SQL 操作之一。然而,許多開發者在執行UPDATE操作時,常常忽略了一個關鍵細節:在執行更新之前,並未驗證是否確實有匹配的記錄。這種忽略,會直接影響到mysqli::$affected_rows屬性的值,進而可能導致程序邏輯錯誤或異常行為。
在MySQLi 中,每次執行數據修改操作(如INSERT 、 UPDATE或DELETE )後, $mysqli->affected_rows會返回受影響的行數。這個值在很多應用場景中被用於判斷操作是否成功,或用於記錄操作日誌等。
例如:
<code> $mysqli = new mysqli("localhost", "user", "pass", "database");$mysqli->query("UPDATE users SET status = 'active' WHERE last_login < NOW() - INTERVAL 30 DAY");
echo $mysqli->affected_rows;
</code>
該代碼會輸出受影響的行數,即成功更新狀態的用戶數量。
當執行的UPDATE語句沒有匹配任何記錄時, $mysqli->affected_rows會返回0 。這是因為沒有任何記錄被修改,無論語法是否正確、SQL 是否成功執行,受影響行數仍為0。
注意:即使SQL 語句語法完全正確,如果WHERE 條件沒有命中任何數據, affected_rows依然為0。這並不代表SQL 執行失敗。
例如:
<code> $mysqli = new mysqli("localhost", "user", "pass", "database");$mysqli->query("UPDATE users SET status = 'active' WHERE id = 999999");
echo $mysqli->affected_rows;
</code>
假設id = 999999的用戶不存在,則輸出將是0 ,說明沒有記錄被更新。
此外,還有一種情況容易被誤解:即使有記錄被匹配,如果更新後的值與原值相同,也不會計入受影響的行數。
例如:
<code> $mysqli = new mysqli("localhost", "user", "pass", "database");$mysqli->query("UPDATE users SET status = 'active' WHERE status = 'active'");
echo $mysqli->affected_rows;
</code>
這段代碼中,雖然可能匹配了許多行,但由於status字段原本就已經是'active' ,所以沒有實際的數據修改動作發生,MySQL 會認為沒有任何行被“影響”,返回0 。
如果你依賴affected_rows來判斷操作是否成功,務必考慮以下兩點:
SQL 執行是否成功(可通過$mysqli->errno或$mysqli->error判斷)
affected_rows是否為正值,表示確實有數據被修改
完整示例:
<code> $mysqli = new mysqli("localhost", "user", "pass", "database");$result = $mysqli->query("UPDATE users SET status = 'inactive' WHERE last_login < NOW() - INTERVAL 1 YEAR");
if ($result === false) {
die("SQL 錯誤:" . $mysqli->error);
} elseif ($mysqli->affected_rows > 0) {
echo "成功更新了{$mysqli->affected_rows} 條記錄。";
} else {
echo "沒有記錄被更新。";
}
</code>
在構建管理系統或接口時,開發者可能希望通過返回affected_rows來驗證客戶端傳入的條件是否命中任何數據。如果沒有事先提醒這一機制,可能會導致客戶端錯誤地認為更新失敗或服務端出錯。
例如,一個接口:
<code> POST /api/update-status.php?user_id=123 HTTP/1.1 Host: m66.net </code>如果用戶ID 不存在,而接口代碼僅根據affected_rows判斷操作是否成功,客戶端可能誤認為系統出錯。應通過更明確的響應信息告知是“無匹配記錄”,而非“操作失敗”。
在PHP 的MySQLi 操作中, $mysqli->affected_rows是判斷數據是否實際發生變動的重要手段。但需要注意的是:
沒有匹配記錄時,值為0
匹配了記錄但更新前後數據相同,也返回0
SQL 執行錯誤不會反映在affected_rows ,需額外判斷
開發者在使用這一屬性時,應全面理解其行為,避免邏輯漏洞或誤判更新結果。