REPLACE INTO 是 MySQL 獨有的擴展語法,兼具插入與更新語義。本文深度解析其執行算法、權限要求、返回值含義及與 INSERT ... ON DUPLICATE KEY UPDATE 的選型建議。
INSERT 邏輯嘗試寫入新行-- VALUES 形式
REPLACE [LOW_PRIORITY | DELAYED] INTO tbl_name [(col_list)] VALUES (val_list),...;
-- SET 形式
REPLACE [LOW_PRIORITY | DELAYED] INTO tbl_name SET col=val, ...;
-- SELECT 形式
REPLACE [LOW_PRIORITY | DELAYED] INTO tbl_name [(col_list)] SELECT ...;
| 特性 | 說明 |
|---|---|
| 前置條件 | 表必須有主鍵或唯一索引,否則退化為 INSERT |
| 權限要求 | 同時需要 INSERT 和 DELETE 權限 |
| 列值來源 | 完全來自語句指定值,缺失列填默認值,不可引用舊行值 |
| 返回值 | 受影響行數 = 刪除行數 + 插入行數。1=純插入,2=一條衝突替換,>2=多索引多衝突 |
| 觸發器 | 觸發 BEFORE/AFTER DELETE + BEFORE/AFTER INSERT |
| 自增 ID | 舊行刪除,新行重新分配(可能導致 ID 變化) |
| 子查詢限制 | 不可在子查詢中 REPLACE 同表並同時 SELECT 該表 |
| 維度 | REPLACE | IODKU |
|---|---|---|
| 語義 | 刪舊插新(全行替換) | 就地更新(部分列更新) |
| 保留未指定列 | 否(填默認值) | 是(保持原值) |
| 自增 ID 穩定性 | 變化 | 不變 |
| 觸發器開銷 | 雙倍(DEL+INS) | 單次 UPDATE |
| 多唯一索引衝突 | 刪除所有衝突行 | 僅更新第一條匹配行 |
| 標準兼容性 | MySQL 專有 | MySQL 擴展(語義更標準) |
created_at、version)、維持自增 ID 穩定、性能敏感場景-- 表:id PK, email UK, name, status
-- 現有:id=1, email='a@b.com', name='Alice', status=1
REPLACE INTO users (id, email, name) VALUES (1, 'a@b.com', 'Alice Updated');
-- 結果:status 重置為默認值 0(丟失原值!)
-- 正確用 IODKU
INSERT INTO users (id, email, name) VALUES (1, 'a@b.com', 'Alice Updated')
ON DUPLICATE KEY UPDATE name=VALUES(name);
-- 結果:status 保持 1
理解 REPLACE 的「刪除重插」本質,謹慎選型,避免靜默數據丟失。