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

PHP 獲取 MySQL 更新影響行數的正確姿勢:mysql_affected_rows 與 ROW_COUNT() 深度解析

     編輯:PHP 相關知識

核心函數對比

方法適用操作返回值含義注意事項
mysql_affected_rows()INSERT/UPDATE/DELETE受影響行數舊擴展,PHP 7 移除
mysqli_affected_rows()INSERT/UPDATE/DELETE受影響行數推薦,面向對象 $mysqli->affected_rows
PDO::rowCount()INSERT/UPDATE/DELETE受影響行數SELECT 不可靠,官方不建議用於 SELECT
SQL ROW_COUNT()INSERT/UPDATE/DELETE受影響行數會話級,緊跟寫操作調用
SQL FOUND_ROWS()SELECT (配合 SQL_CALC_FOUND_ROWS)匹配總行數(忽略 LIMIT)需在 SELECT 前加 SQL_CALC_FOUND_ROWS

mysqli 實戰示例

<?php
$mysqli = new mysqli("localhost", "root", "pass", "test");
$mysqli->set_charset("utf8mb4");

// UPDATE
$mysqli->query("UPDATE users SET status = 1 WHERE status = 0");
echo "更新行數: " . $mysqli->affected_rows . "<br>"; // 正確

// DELETE
$mysqli->query("DELETE FROM logs WHERE created_at < '2023-01-01'");
echo "刪除行數: " . $mysqli->affected_rows . "<br>";

// INSERT
$mysqli->query("INSERT INTO users (name) VALUES ('test')");
echo "新增 ID: " . $mysqli->insert_id . ", 影響行數: " . $mysqli->affected_rows . "<br>";

// 事務中
$mysqli->begin_transaction();
$mysqli->query("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$mysqli->query("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
echo "事務中第一條影響: " . $mysqli->affected_rows; // 僅反映最後一條語句
$mysqli->commit();

PDO 實戰示例

$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

$stmt = $pdo->prepare("UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?");
$stmt->execute([5, 101, 5]);
echo "扣減庫存行數: " . $stmt->rowCount(); // 1 成功,0 庫存不足

// 批量插入
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO logs (msg) VALUES (?)");
foreach ($messages as $msg) {
    $stmt->execute([$msg]);
}
$pdo->commit();
// 注意:rowCount() 僅反映最後一次 execute

SQL 層面 ROW_COUNT() 使用場景

-- 存儲過程中
UPDATE orders SET status = 'paid' WHERE id = 123;
SELECT ROW_COUNT() AS updated_rows; -- 返回 1 或 0

-- 觸發器中
CREATE TRIGGER after_order_update
AFTER UPDATE ON orders
FOR EACH ROW BEGIN
    IF ROW_COUNT() > 0 THEN
        INSERT INTO order_logs (order_id, action) VALUES (NEW.id, 'status_change');
    END IF;
END;

常見誤區與避坑

  1. SELECT 使用 rowCount():PDO 的 rowCount() 對 SELECT 返回值未定義(驅動相關),統計總數請用 SELECT COUNT(*) 或 SQL_CALC_FOUND_ROWS + FOUND_ROWS()。
  2. REPLACE INTO 影響行數:若鍵衝突刪除舊行再插入,返回 2(1 delete + 1 insert)。
  3. INSERT ... ON DUPLICATE KEY UPDATE:新增返回 1,更新返回 2,無變化返回 0。
  4. 事務中 affected_rows:僅反映最後一條語句,需逐條檢查或用 ROW_COUNT()。
  5. 舊 mysql_affected_rows() 異常:若遇到返回 -1,通常是連接斷開或 SQL 語法錯誤,建議遷移至 mysqli/PDO。

兼容性封裝函數(舊項目維護用)

function get_affected_rows($link = null) {
    if (function_exists('mysqli_affected_rows')) {
        return $link ? mysqli_affected_rows($link) : mysqli_affected_rows($GLOBALS['mysqli_link']);
    }
    if (function_exists('mysql_affected_rows')) {
        return $link ? mysql_affected_rows($link) : mysql_affected_rows();
    }
    // PDO 情況下需傳入 Statement 對象
    return -1;
}

總結

  • 新項目:**mysqli->affected_rows** 或 **PDOStatement->rowCount()**(僅寫操作)。
  • 存儲過程/觸發器:**ROW_COUNT()**。
  • 分頁總數:**SQL_CALC_FOUND_ROWS + FOUND_ROWS()** 或單獨 COUNT(*)。
  • 永遠檢查返回值,0 代表「無匹配/無變化」而非錯誤,錯誤需捕獲異常/errno。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved