INSERT INTO tbl(a,b,c) VALUES(1,2,3)
ON DUPLICATE KEY UPDATE c = c + 1;
-- 等價於:若 a=1 存在則 UPDATE,否則 INSERT
-- 返回:INSERT=1 行,UPDATE=2 行
VALUES() 函數引用插入值
INSERT INTO tbl(a,b,c) VALUES
(1,2,3),
(2,5,7),
(3,3,6),
(4,8,2)
ON DUPLICATE KEY UPDATE b = VALUES(b);
執行邏輯:
UPDATE b = VALUES(b),VALUES(b) 取對應行的插入值(5 和 3)VALUES(col) 進階用法
-- 計數器增量
ON DUPLICATE KEY UPDATE cnt = cnt + VALUES(cnt)
-- 多列更新
ON DUPLICATE KEY UPDATE
b = VALUES(b),
c = VALUES(c),
updated_at = NOW()
-- 條件更新(MySQL 8.0.20+)
ON DUPLICATE KEY UPDATE
b = IF(VALUES(b) > b, VALUES(b), b) -- 只增不減
| 操作 | 受影響行數 |
|---|---|
| 新插入 | 1 |
| 更新現有 | 2 |
| 值相同(無實際更新) | 0 (MySQL 8.0.20+ 可配置) |
ON CONFLICT,SQL Server 用 MERGE)ON DUPLICATE KEY UPDATE 可能導致子表外鍵檢查失敗BEFORE INSERT → AFTER INSERT → BEFORE UPDATE → AFTER UPDATE
-- 1. 批量 Upsert 模板
INSERT INTO metrics(day, key, val) VALUES
('2024-01-01','cpu',0.5),
('2024-01-01','mem',0.8)
ON DUPLICATE KEY UPDATE
val = VALUES(val),
updated_at = CURRENT_TIMESTAMP;
-- 2. 配合 rewriteBatchedStatements=true (JDBC) 自動合併多條為批量
-- 3. 大批量分片:每批 1000-5000 行,避免超大 SQL 文本解析開銷