單筆校驗回答的是這一個號碼對不對,批次校驗回答的是這一批資料哪裡有問題、該由誰修。問題一旦變成後者,工作量的大頭就從算法移到流程。本文說明一條可靠的批次流水線該有哪幾段、結果該怎麼分類,以及報告要寫到什麼程度才真的有人能照著修。
批次校驗和單筆校驗差在哪?
最主要的差別是失敗的處理方式。單筆失敗可以當場提示使用者重填;批次裡的一筆失敗,你面對的是一份沒有互動的檔案,必須靠紀錄把問題定位回原始的行。
第二個差別是資料品質。單筆輸入的來源通常是使用者本人,批次資料則可能來自多個系統的匯出檔,混著不同格式、不同編碼、不同習慣的空值表示。清洗的份量因此完全不同。
第三個差別是可重複性。批次流程會被重跑,可能是因為修了資料,也可能是因為規則更新。要能比較兩次結果的差異,輸出就必須是穩定且可對照的。
最後一個差別是責任歸屬。單筆失敗的處理者就是輸入的人;批次失敗的處理者往往不是提供資料的人,而是負責清理的團隊。這使得報告的讀者與資料的來源分離,於是「誰該修」這件事必須在流程設計時就先想清楚,不能等到失敗發生才決定。
先清洗再校驗的流水線
順序很重要:先清洗、再校驗,不要邊校驗邊清洗。混在一起會讓一筆失敗究竟是資料錯還是規則不符變得無法回答。
| 階段 | 做什麼 | 產出 |
|---|---|---|
| 讀入 | 逐行讀取,保留行號 | 原始值與位置 |
| 清洗 | 去空白、統一字元、去除裝飾符號 | 正規化後的值 |
| 分流 | 依長度與字元集選定候選制度 | 每個值的候選清單 |
| 校驗 | 對候選制度逐一檢查 | 四態結論與依據 |
| 輸出 | 分類彙整並寫報告 | 可修的行級清單 |
這五段的界線要清楚,因為它們的失敗原因不一樣。讀入失敗是檔案問題,清洗失敗是格式問題,校驗失敗才是號碼本身的問題。混在一起就只能得到一句沒有用的處理失敗。
清洗階段還有一件事要決定:遇到無法正規化的值時,要讓它繼續往下走,還是直接標記後跳過。兩種做法都合理,但必須固定下來並記錄在報告裡,否則同一份檔案在兩次執行中會得到不同的筆數,後續比對就失去意義。
校驗結果要分成哪幾類?
分類的目的不是好看,而是決定每一類由誰處理。以下是一種實用的分法:
- 校驗通過:演算法成立,可以進入後續流程。
- 校驗失敗:格式符合但校驗位不成立,通常代表抄錄錯誤。
- 僅格式:制度沒有公布演算法,只能確認格式。
- 無規則:找不到對應的公開制度,不能藉此判定號碼有問題。
- 格式不符:長度或字元集就不符合,這是最容易自動修的一類。
第三與第四類最容易被錯誤合併。把它們分開,才不會讓一批本來只是工具沒有規則的資料被當成壞資料丟掉。
分類的粒度也要考慮用途。如果下游只在意可不可以繼續處理,那麼五類可以再合併成兩大類;但合併時要保留原始的分類欄位,否則日後想細分時就沒有資料可拆。
重複項、空值與超大檔案
重複項要在正規化之後才判斷,否則同一個號碼的不同寫法會被當成兩筆。判斷時要用完整值,不要用遮罩後的顯示值,也不要只看最後幾位。
空值要與錯誤分開。空白、佔位符號與未知這類填法在匯出檔裡很常見,把它們當成校驗失敗會製造大量假問題。建議的處理是標成獨立的類別,交給提供資料的一方補齊。
超大檔案的重點是不要整個讀進記憶體。逐行或分塊處理,並讓每一塊的輸出都帶上原始行號,這樣即使中途中斷,也能從上次的位置繼續,而不是整批重來。
還有一個實務上的坑是編碼。同一份檔案裡混著不同來源的資料時,看似相同的字元可能是不同的位元組。若在讀入階段就統一轉換,並在轉換失敗時保留原始位元組的摘要,事後追查才不會只看到一堆問號。
報告怎麼寫才可行動
一份能用的報告要讓收件者一眼知道去哪裡改。最少要包含這幾項:原始行號、原始值、正規化後的值、判定的結論,以及判定所依據的制度或規則。
只寫有若干筆校驗失敗的報告等於沒寫,因為收件者無法定位。反之,把每一筆失敗的原始值都列出來,也未必好用:若檔案裡已經有敏感資料,報告本身就是新的外洩風險,因此輸出前要先想清楚誰能看、要不要遮罩。
摘要與明細應該分開。摘要給管理者看趨勢與工作量,明細給實際修資料的人。兩者混在同一份檔案裡,兩邊都不好用。
給開發者:分塊、並行與冪等
批次流程最值得投資的三個性質,恰好都不是算法:
- 分塊:以固定大小的區塊處理,讓記憶體用量與檔案大小脫鉤,也讓中斷後可以續跑。
- 冪等:同一個輸入重跑兩次得到同樣的結果與同樣的輸出。這要求輸出順序穩定,不能依賴不確定的排程順序。
- 可追溯:每一筆結果都能回到原始行號與原始值,包含被清洗掉的那一部分。
並行會帶來一個容易忽略的陷阱:如果多個工作同時寫同一份報告,結果的順序就會不穩定,兩次跑出來的檔案無法直接比對。做法是各自輸出再合併,或先蒐集再統一排序寫出。
規則版本也要記錄。當規則更新後重跑,有些資料的結論會改變,這本身不是問題;問題是如果沒有記錄用了哪一版規則,就無法解釋為什麼同一批資料上次通過這次失敗。
還有一個容易被低估的性質是資源上限。處理大批資料時,記憶體、檔案句柄與輸出目錄的容量都會成為限制。把上限當成設定值而不是寫死的假設,遇到更大的檔案時才不用改程式。
下一步
先挑一份規模較小的匯出檔,照著上面的五段流程手動走一遍,觀察每一段的失敗數量分布。這一步通常會發現真正的問題不在校驗,而在清洗。接著把流程改成可重跑的版本,並用號碼校驗工具抽驗幾筆的結果是否與報告一致。四態結論的定義讀沒有校驗位的號碼;怎麼在服務端與前端分工,讀介面邊界的校驗。如果你需要一組可以反覆重跑的測試資料來驗證流程穩定,可以參考可重現的測試資料。
本文的批次示例都是為了說明流程而構造的。匯入真實資料前,務必先脫敏並在隔離環境處理,不要讓完整號碼流入日誌、報告或測試檔案。