MySQL 提供 INSERT、INSERT IGNORE、REPLACE INTO 三種插入變體,行為差異直接影響資料完整性與業務邏輯。本文通過建表實驗、執行結果對比、底層機制解析,助你精準選型。
| 語句 | 主鍵/唯一鍵衝突行為 | 非衝突行為 | 影響行數返回 | 觸發器 |
|---|---|---|---|---|
| INSERT | 報錯 (Error 1062),回滾該語句 | 正常插入 | 1 (成功) / 0 (錯誤) | BEFORE/AFTER INSERT 觸發 |
| INSERT IGNORE | 忽略該行,繼續執行,不報錯 (Warning) | 正常插入 | 1 (插入) / 0 (忽略) | 同上,但衝突行不觸發 |
| REPLACE INTO | 刪除舊行 → 插入新行 (實際為 DELETE + INSERT) | 正常插入 | 1 (新增) / 2 (替換: 1刪+1增) | 觸發 DELETE → INSERT 觸發器 |
CREATE TABLE testtb (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(50),
age INT
);
-- 1. 初始插入
INSERT INTO testtb(id,name,age) VALUES(1,'bb',13);
SELECT * FROM testtb; -- 1, 'bb', 13
-- 2. INSERT IGNORE 遇到主鍵衝突
INSERT IGNORE INTO testtb(id,name,age) VALUES(1,'aa',13);
SELECT * FROM testtb; -- 仍為 1, 'bb', 13 (忽略新值)
-- 3. REPLACE INTO 替換
REPLACE INTO testtb(id,name,age) VALUES(1,'aa',12);
SELECT * FROM testtb; -- 變為 1, 'aa', 12 (完整替換)
-- 來源表 table2
id | name
1 | tb
2 | cw
3 | zp
-- 目標表 table1 (id 為 PK)
id | name
1 | tb
2 | zp
-- INSERT IGNORE 複製
INSERT IGNORE INTO table1 SELECT * FROM table2;
-- 結果:table1 變為 1:tb, 2:zp, 3:zp (id=1,2 衝突被忽略,id=3 新增)
-- REPLACE INTO 複製
REPLACE INTO table1 SELECT * FROM table2;
-- 結果:table1 變為 1:tb, 2:cw, 3:zp (id=1,2 刪除重插,id=3 新增)
-- 注意:若 table2 缺少 table1 的某些列 (如 ps),REPLACE 會將該列置為 NULL/DEFAULT
DELETE FROM table WHERE PK=val; INSERT INTO table ...。
BEFORE DELETE、AFTER DELETE、BEFORE INSERT、AFTER INSERT 全套觸發器。ON DELETE CASCADE,會連帶刪除子表資料!INSERT INTO t(id,a,b) VALUES(1,2,3) ON DUPLICATE KEY UPDATE a=VALUES(a), b=VALUES(b);
INSERT IGNORE 最快 (僅索引查找);REPLACE 最慢 (DELETE+INSERT 兩次索引維護);IDKU 介於中間。INSERT ... VALUES (...),(...),... 語法,單條執行開銷巨大。最佳實踐: 90% 場景首選
INSERT ... ON DUPLICATE KEY UPDATE,語意清晰、副作用可控、效能優異。REPLACE INTO僅用於「全行覆蓋且接受副作用」的特定場景。INSERT IGNORE專用於「不關心衝突、追求極致寫入速度」的日志/統計類入庫。