首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP mysql_affected_rows 異常值問題:更新數據未變時返回 0 的解決方案

     編輯:PHP 綜合知識

問題現象

執行 UPDATE 語句時,若 WHERE 條件匹配行但字段值實際未變更,mysql_affected_rows() 返回 0,而非匹配行數。這導致無法區分「未匹配到行」與「匹配但值相同」兩種情況。

官方文檔說明

mysql_affected_rows() 返回上一條 INSERT、UPDATE、DELETE 影響的行數。對於 UPDATE,若新值與舊值相同,MySQL 不會更新行,故返回 0。

解決方案:封裝 mysql_modified_rows()

function mysql_modified_rows() {
    $info = mysql_info(); // 返回如 "Rows matched: 5  Changed: 0  Warnings: 0"
    $affected = mysql_affected_rows();
    if (preg_match('/Rows matched: ([0-9]+)/', $info, $m)) {
        $matched = (int)$m[1];
    } else {
        $matched = 0;
    }
    // 若 affected 為 0 但 matched > 0,說明匹配到行但值未變
    return ($affected > 0) ? $affected : $matched;
}

原理解析

  • mysql_info() 提供「Rows matched」與「Changed」信息
  • 「Rows matched」= WHERE 條件匹配的行數
  • 「Changed」= 實際值發生變化的行數(即 mysql_affected_rows())
  • 封裝函數優先返回 affected,為 0 時回退 matched

遷移至 MySQLi/PDO 的對應處理

MySQLi

$mysqli->query($sql);
$matched = $mysqli->affected_rows; // 同上行為
// 獲取 matched 需啟用 MYSQLI_REPORT_INDEX 或使用 INFO 查詢
// 推薦:$result = $mysqli->query("SELECT ROW_COUNT()"); // 不可靠
// 最佳:使用 PDO

PDO(推薦)

$stmt = $pdo->prepare($sql);
$stmt->execute();
$changed = $stmt->rowCount(); // 行數變更數
// PDO 無直接 matched 獲取,可執行:
$matched = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn(); // 需配合 SQL_CALC_FOUND_ROWS
// 或在 SQL 中加入 RETURNING 子句(MariaDB 10.5+/MySQL 8.0.20+)

最佳實踐建議

  1. 業務邏輯上區分「不存在」與「已是目標值」:先 SELECT 判斷,再決定是否 UPDATE
  2. 使用 UPDATE ... SET col=VAL WHERE id=X AND col<>VAL 讓數據庫層面過濾無效更新,affected_rows 直接反映真實變更
  3. 全項目統一封裝 Database::executeUpdate() 返回 ['matched'=>N, 'changed'=>M]
  4. 棄用 mysql_*,全面遷移至 PDO + 異常模式
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved