Contents

快速調整 INSERT / UPDATE SQL 語法

最近遇到一個很常見的維運場景:兩台資料庫的資料需要補齊,但欄位又不是完全一致。原本我是直接用 DBeaver 產生 INSERT / UPDATE SQL,再手動把不需要的欄位從 Editor 裡面刪掉。結果欄位一多時,這種做法真的很傷眼睛,也很容易刪錯。

後來才發現,這件事其實可以先在資料檢視階段把欄位整理好,再來產生 SQL,效率差很多。

先講問題本質

這種需求通常不是單純的資料匯出,而是:

  • A 資料庫有資料,B 資料庫也要補。
  • 兩邊 schema 類似,但不完全一樣。
  • 我只想同步少數欄位。
  • 還想保留人工檢查 SQL 的能力。

如果直接從完整結果集產生 SQL,再手動刪欄位,當欄位多、資料多時,很容易出現以下問題:

  • 刪錯欄位名稱。
  • INSERT 欄位與 VALUES 對不起來。
  • UPDATE 忘了帶主鍵條件。
  • 把目標資料庫沒有的欄位也一起帶過去。

用 DBeaver 先整理欄位,再產生 SQL

我後來覺得最省力的做法,是先在 DBeaver 把要看的欄位縮到最小,再做 SQL Generation。

相關功能可參考:

實務流程

  1. 先查出你要同步的資料。
  2. 用 Data Filters 或欄位顯示設定,把不需要的欄位先隱藏。
  3. 確認保留下來的欄位剛好是目標資料庫也存在的欄位。
  4. 再從結果集產生 INSERT 或 UPDATE SQL。

這樣最大的好處是:你不是在一大串產生好的 SQL 裡面做肉眼編修,而是在結構比較清楚的表格視圖先把資料面整理乾淨。

INSERT 與 UPDATE 的注意點不一樣

產生 INSERT 時

INSERT 的重點是:

  • 欄位順序與 VALUES 順序要一致。
  • 目標資料庫沒有的欄位不要帶。
  • 自動產生欄位、流水號欄位要先確認要不要排除。

像這樣的 SQL:

1
2
INSERT INTO employee (id, name, status)
VALUES (1001, 'steve', 'ACTIVE');

如果 id 在目標資料庫是自增欄位,這段就可能要調整。

產生 UPDATE 時

UPDATE 最容易出包的是沒帶正確條件。

例如:

1
2
3
UPDATE employee
SET status = 'ACTIVE'
WHERE id = 1001;

我自己的習慣是:只要是產生 UPDATE,一定確認主鍵或唯一鍵條件有被帶上,不然一個不小心就可能變成整批更新。

UPDATE 一定要確認條件
不管工具幫你產得多漂亮,真正要執行前還是要再檢查一次 WHERE 條件,尤其是正式環境。

如果 DBeaver 還是不夠用

有些情況欄位差異太大,或你需要先做 mapping、轉型、資料清洗,這時候我會考慮第二種方式:先建立臨時表,再做匯入與轉換。

流程大概是:

  1. 在本地或測試資料庫先建立暫存表。
  2. 把來源資料匯進暫存表。
  3. 用 SQL 明確寫出要同步到目標表的欄位。
  4. 最後再輸出正式要執行的 INSERT / UPDATE。

這種做法雖然步驟比較多,但好處是:

  • 欄位映射比較清楚。
  • 可以先做資料清洗。
  • 比較適合大量資料或多欄位轉換。

什麼情況適合哪一種方法

我自己的判斷是:

  • 欄位差異不大、只是想快速補資料:直接用 DBeaver。
  • 欄位差異大、還要轉型或清洗:先走暫存表。
  • 資料量很大、需要重複執行:考慮寫成正式 SQL script 或 ETL 流程。

補充:CSV 也是一條路

如果你拿到的是 CSV,而不是直接查資料庫,也可以先匯入再處理:

這條路特別適合來源資料不是你直接能連線的資料庫,而是別人丟給你的匯出檔。

小結

這篇的核心其實很簡單:不要把欄位刪除工作留到最後一刻的 SQL 編修階段,而是盡量往前移,在資料檢視與欄位過濾階段就處理掉。

我目前還是覺得 DBeaver 先過濾欄位、再產生 SQL,是這種臨時資料同步需求最省時間的方法。