需一次性將多行記錄的 myfield 更新為不同值,避免循環 UPDATE 產生的高延遲、鎖競爭、網路往返。
UPDATE mytable
SET myfield = CASE id
WHEN 1 THEN 'v1'
WHEN 2 THEN 'v2'
WHEN 3 THEN 'v3'
END
WHERE id IN (1,2,3);
$ids_values = [1=>11, 2=>22, 3=>33];
$ids = implode(',', array_keys($ids_values));
$sql = "UPDATE mytable SET myfield = CASE id ";
foreach ($ids_values as $id=>$val) $sql .= "WHEN $id THEN $val ";
$sql .= "END WHERE id IN ($ids)";
REPLACE INTO mytable (id, myfield) VALUES (1,'v1'),(2,'v2'),(3,'v3');
DELETE + INSERT,非衝突列會重置為預設值,慎用於寬表。INSERT INTO mytable (id, myfield1, myfield2) VALUES
(1,'v11','v21'),(2,'v12','v22'),(3,'v13','v23')
ON DUPLICATE KEY UPDATE
myfield1=VALUES(myfield1), myfield2=VALUES(myfield2);
VALUES(col) 引用插入值,可進行運算如 myfield2=VALUES(myfield2)+VALUES(id)。DROP TEMPORARY TABLE IF EXISTS tmptable;
CREATE TEMPORARY TABLE tmptable (id INT PRIMARY KEY, myfield VARCHAR(50));
INSERT INTO tmptable VALUES (1,'v1'),(2,'v2'),(3,'v3');
UPDATE mytable m JOIN tmptable t ON m.id = t.id SET m.myfield = t.myfield;
CREATE TEMPORARY TABLES 權限。LOAD DATA INFILE 秒級導入臨時表。| 數據量 | 推薦方案 | 理由 |
|---|---|---|
| < 1,000 行 | CASE WHEN / ON DUPLICATE KEY | 單語句、無額外對象、應用層構建簡單 |
| 1,000 - 50,000 行 | ON DUPLICATE KEY / 臨時表 | 平衡開發效率與執行效能 |
| > 50,000 行 | 臨時表 + LOAD DATA | 避免 SQL 解析瓶頸、批量導入最快 |
REPLACE INTO 會導致 auto_increment 增長、觸發器雙火、外鍵級聯,嚴禁用於有關聯表的主表。CASE WHEN 若 WHERE 範圍超過 WHEN 覆蓋,未匹配行該欄位將置 NULL (非預期) —— 建議 ELSE myfield 保持原值。選對工具,批量更新從「整晚跑」變成「秒級完」。