業務常見需求:「資料存在則更新,不存在則插入」。SQL Server 用 IF NOT EXISTS ... INSERT ELSE UPDATE,MySQL 有更簡潔的 REPLACE INTO。本文詳細對比 REPLACE INTO、INSERT IGNORE、ON DUPLICATE KEY UPDATE 三者差異,說明 REPLACE INTO 的「刪除舊行再插入」機制、三種語法形式、主鍵/唯一索引前置條件與自增 ID 變更副作用。
| 語法 | 衝突處理 | 自增 ID | 觸發器 | 適用場景 |
|---|---|---|---|---|
| INSERT IGNORE | 跳過、不報錯 | 不變 | 不觸發 | 冪等寫入、日誌 |
| ON DUPLICATE KEY UPDATE | 更新指定欄位 | 不變 | 觸發 UPDATE | 計數器、Upsert |
| REPLACE INTO | DELETE 舊行 + INSERT 新行 | 重新分配 | 觸發 DELETE + INSERT | 全行替換、結構同步 |
無唯一約束時,REPLACE INTO 退化為單純 INSERT,導致重複資料。
-- 1. VALUES 形式(最常用)
REPLACE INTO t(id, update_time) VALUES(1, NOW());
-- 2. SELECT 形式
REPLACE INTO t(id, update_time) SELECT 1, NOW();
-- 3. SET 形式
REPLACE INTO t SET id=1, update_time=NOW();
INTO 關鍵字可省略,建議保留以提高可讀性。未指定欄位將自動填入預設值。
CREATE TABLE user_session (
user_id INT PRIMARY KEY,
token CHAR(32),
last_active TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 用戶登入/心跳:存在則刷新 token/時間,不存在則建立
REPLACE INTO user_session (user_id, token) VALUES (1001, 'abc123...');
AUTO_INCREMENT 主鍵且未在 REPLACE 中指定,新行將獲得新 ID,舊 ID 釋放 → 關聯表外鍵失效。ON DELETE CASCADE 子表,舊行刪除會連帶刪除子表資料。BEFORE DELETE、AFTER DELETE、BEFORE INSERT、AFTER INSERT 全走一遍。ON DUPLICATE KEY UPDATE 慢(兩次寫入、索引維護)。理解「刪除再插入」本質,才能在正確場景用好 REPLACE INTO。