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

MySQL 根據 A 表更新 B 表:從 Python 循環到單條 SQL 的重構

     編輯:MySQL 綜合教學

常見需求:依據表 B 的資料更新表 A 對應欄位。許多開發者習慣在應用層「讀 B → 循環更新 A」,實則 MySQL 單條 UPDATE ... JOIN 即可完成,效能提升數量級。本文以實際案例示範重構過程。

場景定義

表欄位樣本資料
A 表 (table_a)id (PK), name, age(1,'n1',0), (2,'n2',0), (3,'n3',0), (4,'n4',0), (5,'n5',0)
B 表 (table_b)id (PK), age(1,11), (2,21), (3,31), (4,41), (5,51)

❌ 反模式:應用層循環更新 (Python)


rs = db.query("SELECT id, age FROM table_b")
for row in rs:
    idv, age = row
    sql = "UPDATE table_a SET age='%s' WHERE id='%s'" % (age, idv)
    db.update(sql)
# 5 次查詢 + 5 次更新 = 10 次網路往返

✅ 最佳模式:單條多表 UPDATE


UPDATE table_a a
INNER JOIN table_b b ON a.id = b.id
SET a.age = b.age;
-- 1 次 SQL,原子執行,毫秒級完成

為何單條 SQL 碾壓應用層循環?

維度應用層循環單條 UPDATE JOIN
網路往返2N 次1 次
SQL 解析/優化N 次1 次
事務一致性需手動管理隱式原子事務
鎖持有時間分散、總時間長集中、總時間極短
程式碼複雜度高(連線、異常、重試)極低

擴展場景與寫法

1. 部分欄位同步 + 條件過濾


UPDATE table_a a
JOIN table_b b ON a.id = b.id
SET a.age = b.age, a.updated_at = NOW()
WHERE b.status = 1 AND a.age != b.age;  -- 只更新有變化的

2. 衍生表來源(複雜聚合後更新)


UPDATE table_a a
JOIN (
    SELECT user_id, COUNT(*) AS cnt FROM logs 
    WHERE create_time > DATE_SUB(NOW(), INTERVAL 1 DAY)
    GROUP BY user_id
) l ON a.id = l.user_id
SET a.daily_log_count = l.cnt;

3. LEFT JOIN 保留目標表所有行


UPDATE table_a a
LEFT JOIN table_b b ON a.id = b.id
SET a.age = COALESCE(b.age, a.age);  -- B 無資料時保持原值

避坑指南

  • 索引必備:JOIN ON 條件欄位雙方必須有索引(通常是主鍵)。
  • 資料型別一致:a.age 與 b.age 型別需相容,否則隱式轉換導致索引失效/精度損失。
  • 大表分批:超過 5 萬行建議分批:WHERE a.id BETWEEN 1 AND 10000 循環執行,避免長鎖/大事務。
  • 測試先行:先跑 SELECT a.id, a.age, b.age FROM table_a a JOIN table_b b ON a.id = b.id 確認關聯正確,再改為 UPDATE。

核心心法

「能用單條 SQL 解決的,就不要寫循環。」 將集合運算思維內化,是從 CRUD 碼農進階為資料庫工程師的分水嶺。

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