首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 原生 UPSERT 寫法總結:INSERT IGNORE、ON DUPLICATE KEY UPDATE、REPLACE INTO 三大方案對比

     編輯:MySQL 資料庫相關知識

業務常見「存在則更新、不存在則插入」需求,Hibernate 提供 saveOrUpdate,原生 SQL 有三種標準寫法。本文詳細對比 INSERT IGNORE、INSERT ... ON DUPLICATE KEY UPDATE、REPLACE INTO 的語法、語義差異、觸發器行為、主鍵/唯一鍵要求、性能特徵與適用場景。

一、方案 1:INSERT IGNORE(不存在插入,存在靜默忽略)

INSERT IGNORE INTO tbl_name (col1, col2) VALUES (val1, val2);
  • 語義:主鍵/唯一鍵衝突時,不報錯、不更新、不插入,返回受影響行 0。
  • 適用:冪等導入、去重入庫、不關心現有行是否更新。
  • 陷阱:隱藏所有錯誤(外鍵、字段長度、非空約束等),僅產生 Warning,排查極難。

二、方案 2:INSERT ... ON DUPLICATE KEY UPDATE(標準 UPSERT,推薦)

INSERT INTO tbl_name (pk, col1, col2) VALUES (1, 'a', 'b')
ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2);
  • 語義:主鍵/唯一鍵衝突時,執行 UPDATE;否則 INSERT。返回 1 (新增) / 2 (更新)。
  • VALUES(col) 引用插入值,避免重複寫字面量。
  • 適用:計數器增量、最後更新時間刷新、業務層 UPSERT 邏輯。
  • 觸發器:觸發 BEFORE INSERT、BEFORE UPDATE、AFTER INSERT、AFTER UPDATE(視執行路徑)。

三、方案 3:REPLACE INTO(刪除舊行 + 插入新行)

REPLACE INTO tbl_name (pk, col1, col2) VALUES (1, 'a', 'b');
  • 語義:主鍵/唯一鍵衝突時,先 DELETE 舊行,再 INSERT 新行。
  • 副作用:自增 ID 變更、外鍵級聯刪除、觸發 DELETE/INSERT 觸發器、binlog 記錄為 DELETE+INSERT(備庫回放開銷大)。
  • 適用:極少見,僅當業務確需「完全替換行」且無外鍵依賴時。

四、對比總結表

維度INSERT IGNOREON DUPLICATE KEY UPDATEREPLACE INTO
衝突動作忽略更新刪除+插入
返回行數0/11(新增)/2(更新)1(刪除)+1(插入)=2
自增 ID不變不變變更
觸發器僅 INSERT 類INSERT/UPDATE 類DELETE+INSERT 類
隱藏錯誤是(危險)否否
推薦場景冪等去重導入業務 UPSERT(首選)極特殊替換需求

五、最佳實踐建議

  1. 默認首選 ON DUPLICATE KEY UPDATE,語義清晰、不隱藏錯誤、自增 ID 穩定。
  2. 大批量冪等導入(如日志同步)可用 INSERT IGNORE,但必須配合嚴格的數據校驗流程。
  3. 禁用 REPLACE INTO,除非經架構評審確認無外鍵、無觸發器、自增 ID 不被引用。
  4. 複合唯一鍵 UPSERT 時,ON DUPLICATE KEY UPDATE 會匹配任一唯一鍵衝突,確保業務邏輯與索引設計一致。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved