首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 批量更新多行數據:CASE WHEN 與 INSERT ... ON DUPLICATE KEY UPDATE 兩大高效方案

     編輯:MySQL 綜合教學

MySQL 批量更新多行數據:告別循環 UPDATE,單語句搞定

當需要根據不同主鍵更新不同值時,循環執行多條 UPDATE 會產生大量網絡往返與解析開銷。MySQL 提供兩種單語句批量更新方案,大幅降低交互次數,提升吞吐。

方案一:CASE WHEN 條件構造

利用 CASE 表達式在單條 UPDATE 中根據主鍵賦予不同值。

UPDATE categories
SET display_order = CASE id
    WHEN 1 THEN 3
    WHEN 2 THEN 4
    WHEN 3 THEN 5
    END,
title = CASE id
    WHEN 1 THEN 'New Title 1'
    WHEN 2 THEN 'New Title 2'
    WHEN 3 THEN 'New Title 3'
    END
WHERE id IN (1,2,3);

PHP 動態構造示例:

$display_order = [1=>4, 2=>1, 3=>2, 4=>3, 5=>9, 6=>5, 7=>8, 8=>9];
$ids = implode(',', array_keys($display_order));
$sql = "UPDATE categories SET display_order = CASE id ";
foreach ($display_order as $id => $ordinal) {
    $sql .= sprintf("WHEN %d THEN %d ", $id, $ordinal);
}
$sql .= "END WHERE id IN ($ids)";
// 執行 $sql

優點:標準 SQL,跨庫兼容;注意:超長 SQL 可能受 max_allowed_packet 限制,極大批次建議分批。

方案二:INSERT ... ON DUPLICATE KEY UPDATE(MySQL 專有)

利用主鍵/唯一鍵衝突觸發更新,適合「不存在則插入,存在則更新」的業務(Upsert)。

INSERT INTO t_member (id, name, email) VALUES
(1, 'nick', 'nick@126.com'),
(4, 'angel','angel@163.com'),
(7, 'brank','ba198@126.com')
ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email);

VALUES(col) 引用插入行中對應列的值,避免重複書寫。

優點:語句緊湊,天然支持批量 Upsert;缺點:非標準 SQL,遷移其他庫需改寫;若表有自增主鍵且插入行指定了 id,需確保無主鍵衝突導致非預期更新。

性能對比與選型建議

維度CASE WHENON DUPLICATE KEY UPDATE
SQL 標準性標準MySQL 專有
適用場景純更新、多字段不同值Upsert、主鍵衝突即更新
批量大小限制受 max_allowed_packet 限制同樣受限,但語句更緊湊
索引要求無額外要求需主鍵或唯一索引
觸發器行為觸發 UPDATE 觸發器觸發 INSERT/UPDATE 觸發器(視衝突)

最佳實踐

  • 中小批次(<1k 行)優先用 CASE WHEN,通用性強。
  • 大批次 Upsert 業務用 ON DUPLICATE KEY UPDATE,配合分批提交(如每 500 行)。
  • 關閉自動提交(SET autocommit=0)並顯式事務提交,進一步減少日志刷盤開銷。
  • 監控 max_allowed_packet,必要時調大(如 64M)。

總結

單條 SQL 批量更新是減少數據庫交互、提升寫入吞吐的關鍵手段。根據業務是「純更新」還是「Upsert」,選擇 CASE WHEN 或 ON DUPLICATE KEY UPDATE,並注意分批與參數調優,即可獲得數量級性能提升。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved