電影表 movie(id PK, orderby),初始 id=1..10 對應 orderby=1..10。需將 id=9 移至第 3 位,原 3-8 位順延 (orderby+1)。單條 SQL 解決,避免循環多次更新。
REPLACE INTO movie (id, orderby) VALUES
(9, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9);
機制:
限制:
INSERT INTO movie (id, orderby) VALUES
(9, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)
ON DUPLICATE KEY UPDATE `orderby` = VALUES(`orderby`);
機制:
VALUES(col) 取自 VALUES 子句中該列的值優勢:
UPDATE count = count + 1 或 UPDATE count = VALUES(count) + 1| 維度 | REPLACE INTO | INSERT ... ON DUPLICATE KEY UPDATE |
|---|---|---|
| 底層操作 | DELETE + INSERT | INSERT 或 UPDATE |
| 觸發器 | 激活 BEFORE/AFTER DELETE & INSERT | 僅激活 BEFORE/AFTER INSERT 或 UPDATE |
| 外鍵級聯 | 觸發 ON DELETE CASCADE | 不觸發 |
| 自增 ID | 可能重置/產生新 ID | 保持不變 |
| 列值保留 | 全覆蓋 (未指定列變默認值/NULL) | 可指定更新列,其餘保留 |
| 多唯一鍵衝突 | 刪除所有衝突行再插入 | **僅更新第一個匹配行** (有歧義風險) |
| 適用場景 | 全行覆蓋、無外鍵/觸發器、不介意自增變化 | **絕大多數業務場景首選** |
-- 批量插入/更新,統計點擊數
INSERT INTO stats (date, page, clicks) VALUES
('2024-01-01', '/home', 1),
('2024-01-01', '/about', 1)
ON DUPLICATE KEY UPDATE clicks = clicks + VALUES(clicks);
-- 衝突時 clicks = 原值 + 1 (VALUES(clicks)=1)
注意: VALUES(col) 僅在 ON DUPLICATE KEY UPDATE 子句中有效,其他場合返回 NULL。
INSERT DELAYED ... ON DUPLICATE KEY UPDATE 中 DELAYED 會被忽略max_allowed_packet-- 將 @target_id 移至 @new_pos,區間 [@new_pos, @old_pos) 順延
-- 假設 @target_id=9, @old_pos=9, @new_pos=3
INSERT INTO movie (id, orderby) VALUES
(9, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)
ON DUPLICATE KEY UPDATE orderby = VALUES(orderby);
**單條 SQL、原子操作、無副作用、效能最優** — 這是處理「移動排序」類問題的標準解法。