MySQL 提供兩個函數判斷上一條語句影響行數,行為與 Oracle/SQL Server 截然不同,易造成遷移專案的 Bug,必須釐清。
| 函數 | 適用場景 | 核心規則 |
|---|---|---|
FOUND_ROWS() | SELECT 查詢返回行數 | 配合 SQL_CALC_FOUND_ROWS 使用,忽略 LIMIT 返回總行數 |
ROW_COUNT() | INSERT/UPDATE/DELETE 影響行數 | 僅記錄真正修改的行,值未變更則不計入 |
-- MySQL 測試
UPDATE t SET address='weifang' WHERE id=1; -- 原值已是 weifang
SELECT ROW_COUNT(); -- 返回 0 (未實際修改)
UPDATE t SET address='beijing' WHERE id=1; -- 值改變
SELECT ROW_COUNT(); -- 返回 1
-- Oracle 測試 (SQL%ROWCOUNT)
UPDATE t SET address='weifang' WHERE id=1; -- 原值已是 weifang
-- SQL%ROWCOUNT 返回 1 (只要符合 WHERE 條件即計數)
-- SQL Server 測試 (@@ROWCOUNT)
UPDATE t SET address='weifang' WHERE id=1; -- 原值已是 weifang
-- @@ROWCOUNT 返回 1 (同上)
PREPARE / EXECUTE / DEALLOCATE PREPARE 序列中,ROW_COUNT() 必須緊接在 EXECUTE 之後調用,放在 DEALLOCATE 後會返回 -1。TRUNCATE TABLE 屬於 DDL,隱含提交,無法在事務中回滾,且不更新 ROW_COUNT()。INSERT ... SELECT 返回實際插入行數,重複鍵衝突導致失敗時為 0 (除非用 IGNORE/ON DUPLICATE KEY UPDATE)。ROW_COUNT() > 0;Oracle/SQL Server 需額外比對舊值。SELECT 比對,避免無效寫入產生不必要的 Binlog 與鎖開銷。ROW_COUNT() 立即存入變數,防止後續語句覆蓋。