理想設計:字段定義為 NUMBER + 前端輸入校驗。現實:歷史系統無約束,數據已入庫,需清洗遷移。
PHONE
---------------
13800138000
021-88888888
(010) 66668888
張三 13912345678
聯系電話:13600001111
無電話
N/A
NULL
編寫函數 clean_phone(p_str VARCHAR2) RETURN NUMBER,內部多層 IF/ELSE、REGEXP_LIKE、SUBSTR、TRANSLATE 組合,維護成本極高。
SELECT
phone AS original,
REGEXP_REPLACE(phone, '[^0-9]', '') AS digits_only,
CASE
WHEN REGEXP_LIKE(REGEXP_REPLACE(phone, '[^0-9]', ''), '^1[3-9]\d{9}$') THEN '手機'
WHEN REGEXP_LIKE(REGEXP_REPLACE(phone, '[^0-9]', ''), '^0\d{2,3}\d{7,8}$') THEN '座機'
ELSE '異常'
END AS type
FROM contact_table;
REGEXP_REPLACE(phone, '[^0-9]', ''):刪除所有非數字字符,保留純數字串
[^0-9]:匹配任意非 0-9 字符'',等價於「只保留數字」REGEXP_LIKE(str, pattern):判斷清洗後字符串是否符合手機/座機格式| 原始值 | 純數字 | 類型判斷 |
|---|---|---|
| 13800138000 | 13800138000 | 手機 ✅ |
| 021-88888888 | 02188888888 | 座機 ✅ |
| (010) 66668888 | 01066668888 | 座機 ✅ |
| 張三 13912345678 | 13912345678 | 手機 ✅ |
| 聯系電話:13600001111 | 13600001111 | 手機 ✅ |
| 無電話 | (空串) | 異常 ⚠️ |
| N/A | (空串) | 異常 ⚠️ |
| NULL | NULL | 異常 ⚠️ |
UPDATE contact_table
SET phone_clean = REGEXP_REPLACE(phone, '[^0-9]', ''),
phone_type = CASE
WHEN REGEXP_LIKE(REGEXP_REPLACE(phone, '[^0-9]', ''), '^1[3-9]\d{9}$') THEN 'MOBILE'
WHEN REGEXP_LIKE(REGEXP_REPLACE(phone, '[^0-9]', ''), '^0\d{2,3}\d{7,8}$') THEN 'LANDLINE'
ELSE 'INVALID'
END,
clean_time = SYSDATE
WHERE phone_clean IS NULL; -- 增量清洗
REGEXP_REPLACE 需 Oracle 10g+,10gR1 僅支持 REGEXP_LIKE/INSTR/SUBSTR,舊版本用 TRANSLATE + 多次 REPLACEWHERE rownum <= 10000 循環),避免 Undo 表空間爆滿「設計之初定 NUMBER」是根治,「正則一行提取數字」是救命稻草。REGEXP_REPLACE(col, '[^0-9]', '') 配合 REGEXP_LIKE 分類,將 VARCHAR2 臟數據清洗為標準 NUMBER,簡潔高效、易維護、可增量。新系統**堅決拒絕**電話、身份證、銀行卡等純數字業務鍵使用 VARCHAR2 存儲。