用 Claude Code 自建跨資料庫稽核工具:一支拋棄式查詢腳本的演進


大部分 Claude Code 文章講的是「修別人的 bug」「寫產品功能」。但有一類用法被低估了:為自己 scaffold 一支拋棄式的內部工具

保險機構公告更新了一批代碼的點數值。我需要確認:全部幾百個租戶資料庫裡,哪些的點數還是舊的、哪些已經對了、哪些根本沒這筆資料。沒有現成工具能查這個——所以我用 Claude Code 現做了一支。這篇記錄這支跨資料庫稽核腳本的演進,以及為什麼「自建工具」是 Claude Code 最自然的場景之一。


需求:跨幾百個租戶庫的點數稽核

系統是多租戶架構,每個機構一個獨立資料庫(demo-org-2demo-org-81…,幾百個)。保險點數更新後,我要回答:

  • 每個租戶庫的 service_record_03 表裡,代碼的當前點數(Q7 欄位)對不對?
  • 跟官方公告的新點數比,是 match(已更新)、diff(還是舊的)、還是 missing(沒這筆)?

手動一個庫一個庫查?幾百個庫,不可能。所以需要一支跨庫掃描 + 比對 + 出報表的工具。


Claude Code scaffold 出來的東西

一句需求,Claude Code 做出 update_service_record_03_points_query.php——一支跑在瀏覽器的唯讀稽核網頁:

// 核心邏輯(簡化)
// 1. 列出所有租戶庫
$dbs = query("SHOW DATABASES LIKE 'demo-org-%'");

// 2. 逐庫比對
foreach ($dbs as $db) {
    $rows = query("SELECT code, Q7 FROM `$db`.service_record_03");
    foreach ($rows as $r) {
        $expected = $newPoints[$r['code']] ?? null;
        if ($expected === null)        $status = 'missing';
        elseif ($r['Q7'] == $expected) $status = 'match';
        else                           $status = 'diff';
        // 累積到報表
    }
}

// 3. 輸出彩色報表:機構名 / OrgID / 測試帳號 / match-diff-missing 統計

特徵:

  • SHOW DATABASES LIKE 'demo-org-%' 遍歷所有租戶庫
  • 逐庫比對當前點數 vs 公告新點數
  • 輸出 match / diff / missing 彩色報表,含 OrgID、機構名稱、測試帳號
  • 可帶日期區間查詢

這是一支拋棄式工具——放在 schedule/ 目錄,透過瀏覽器手動跑,不是產品功能。用完這次稽核,它的任務就結束了。


8 個 commit 的真實演進

工具不是一次寫對的。issue-1212 有 8+ 個 commit,每個都是踩到一個真實狀況後的調整:

演進一:Q16 欄位的 schema 相容性

不同租戶庫的 service_record_03 表 schema 不完全一樣——有些有 Q16 欄位,有些沒有。

commit abfd3684: 先做「Q16 欄位存在才用」的動態檢查

commit 6c701d65: 還原成直接用 Q16,改成跳過沒有 Q16 的 demo-org-50

這個來回很真實:一開始想做「優雅的」動態 schema 偵測(每個庫先查有沒有 Q16 欄位),但發現只有一個庫(demo-org-50)沒這欄位。與其為一個特例做複雜的動態偵測,不如直接跳過那個庫——務實的退讓。

這是自建工具的常見取捨:它是拋棄式的,不需要處理所有 edge case,只要能完成這次稽核就好。為一個特例寫優雅的通用邏輯,是過度工程。

演進二:命名衝突

commit 7fa3b3dc: 把 part2 改名 part3,避免與 release 分支衝突

工具有多個版本檔(part2、part3)。某次發現檔名跟 release 分支上的東西衝突,改個名避開。小坑,但真實——多人協作的 repo,連臨時工具的命名都可能撞車。

演進三:查詢範圍收斂

commit 52170e3b: 只查居護資料庫(service_type = ServiceTypeB)
              + 過濾補報記錄(A19 = '1')

最初掃所有租戶庫,後來發現只有特定服務類型的庫需要查,而且要排除「補報」記錄(會干擾比對)。範圍從「全部」收斂到「真正相關的子集」——這也是稽核工具常見的演進:先撈全部,再根據實際資料縮範圍。


為什麼「自建工具」是 Claude Code 的甜蜜區

特性為什麼適合 Claude Code
一次性、拋棄式不用考慮長期維護、測試覆蓋、優雅架構——能跑就好
規格明確「掃所有庫、比對點數、出報表」需求清楚
重複的樣板跨庫遍歷、連線、比對、輸出 HTML 都是樣板程式碼
快速迭代跑一次發現問題(某庫沒 Q16)→ 馬上調 → 再跑

傳統上,「為了查一件事而寫一支工具」的成本很高——可能要半天,所以大家寧願手動查或寫一次性的髒 SQL。Claude Code 把這個成本壓到幾分鐘,讓「自建工具」變成可行的日常選項

需求一出現(「我要查全部租戶庫的點數對不對」),與其手動撈,不如花 5 分鐘讓 Claude Code scaffold 一支專用工具。工具跑完即棄,但這次稽核做得又快又完整。


拋棄式工具的紀律

「拋棄式」不代表沒紀律。這支工具有幾個關鍵原則:

  1. 唯讀:稽核工具只 SELECT,絕不寫入。跨幾百個庫的工具如果會寫,風險太大
  2. 放對地方:放在 schedule/(維運腳本目錄),不混進產品 code
  3. 務實處理特例:一個庫沒 Q16 就跳過,不為特例做複雜邏輯
  4. 收斂範圍:從「全部」縮到「真正相關的」,減少雜訊和誤判

唯讀這條最重要——跨資料庫的工具,一律先假設它可能在幾百個庫上跑錯,所以只准查、不准改。要改資料是另一回事(要有 dryrun、要 review,像我寫過的回滾腳本那樣)。


給其他人的借鑑

下次你遇到「我需要查一件事,但沒有現成工具」時:

  1. 別手動撈:如果要查的範圍大(跨多個庫/檔案/環境),花幾分鐘讓 Claude Code scaffold 一支專用工具,比手動快又完整
  2. 明確定義輸出:跟 Claude Code 講清楚「要 match/diff/missing 三種狀態的報表」,它才知道做什麼
  3. 唯讀優先:稽核/查詢工具只查不改,降低跨環境跑錯的風險
  4. 接受拋棄式:不用追求優雅,能完成這次任務就好;特例直接跳過,別過度工程
  5. 放對目錄:臨時工具放維運/腳本目錄,別污染產品 code

結語

Claude Code 最被低估的用法,不是「幫我修這個 bug」,而是「幫我做一支查這件事的工具」。

當建工具的成本從半天壓到幾分鐘,你會開始為很多以前「忍一忍手動查」的事情做專用工具——跨庫稽核、資料比對、批次檢查。這支點數查詢工具就是這樣來的:一個臨時需求,一支拋棄式工具,8 個 commit 處理完真實的 schema 差異和範圍收斂,稽核做完它就功成身退。

下次別再手動撈幾百個資料庫了。把需求講清楚,讓 Claude Code 幫你做一支。