萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL ON DUPLICATE KEY UPDATE 實戰:Upsert 語法、多欄位更新、VALUES() 函數引用與 IGNORE/REPLACE 對比

核心語法

INSERT INTO table (cols) VALUES (vals)
ON DUPLICATE KEY UPDATE col1 = expr1, col2 = expr2, ...;

行為邏輯

  • 嘗試插入新行
  • 若主鍵或唯一鍵衝突 → 更新現有行 指定欄位
  • 受影響行數:1 (新增) / 2 (更新)

實戰範例

1. 計數器原子增長(單欄位更新)

INSERT INTO osc_visit_stats (stat_date, type, id, view_count)
VALUES (?, ?, ?, 1)
ON DUPLICATE KEY UPDATE view_count = view_count + 1;
-- 復合主鍵 (stat_date, type, id)

2. 多欄位更新(訪問記錄:計數+IP+時間)

INSERT INTO osc_space_visit_records (space, user, visit_count, ip, visit_time)
VALUES (?, ?, 1, ?, NOW())
ON DUPLICATE KEY UPDATE
    visit_count = visit_count + 1,
    ip = VALUES(ip),
    visit_time = NOW();

3. VALUES() 函數引用插入值(批量 Upsert 必備)

INSERT INTO table (a, b, c) VALUES (1, 2, 3), (4, 5, 6)
ON DUPLICATE KEY UPDATE c = VALUES(a) + VALUES(b);
-- 等效於:
-- (1,2,3) 衝突 → c = 1+2 = 3
-- (4,5,6) 衝突 → c = 4+5 = 9

關鍵注意事項

  • 唯一鍵衝突判定:任一唯一索引/主鍵衝突均觸發 UPDATE
  • 多唯一鍵風險:表有多個唯一索引時,衝突行不確定(取第一個匹配的),盡量避免 在多唯一鍵表使用
  • DELAYED 忽略:INSERT DELAYED ... ON DUPLICATE KEY UPDATE 中 DELAYED 無效
  • 自增 ID:衝突更新不消耗自增值;REPLACE INTO 會消耗(刪除舊行重新插入)

三大 Upsert 方案對比

方案衝突行處理自增 ID外鍵安全適用場景
INSERT IGNORE靜默跳過,不插入不更新消耗安全只需「不存在則插入」,如日誌去重
REPLACE INTO刪除舊行 + 插入新行消耗(重新分配)危險(觸發級聯刪除)需完全替換整行、無外鍵依賴
INSERT ... ON DUPLICATE KEY UPDATE就地更新指定欄位保留安全計數器、狀態更新、最後訪問時間等首選

最佳實踐建議

  1. 核心業務 Upsert 首選 ON DUPLICATE KEY UPDATE
  2. 2. 明確列出更新欄位,避免 UPDATE col = VALUES(col) 全欄位更新 3. 批量 Upsert 使用 VALUES() 引用插入值,單條 SQL 完成多行 4. 表設計階段規劃唯一索引,支撐 Upsert 語義 5. 監控 Innodb_row_lock_waits、死鎖日誌,優化熱點行併發
copyright © 萬盛學電腦網 all rights reserved