在數據入庫(ETL)過程中,目標字段定義為 NUMBER 類型,但源端數據往往夾雜中文、特殊字符或無意義英文,導致插入報錯。通用做法是編寫一個判斷函數:是數字則保留原值,非數字則轉為 NULL,保證載入流程不中斷。本文提供一個健壯的 ISNUM 函數實現,並說明關鍵邏輯與使用場景。
VARCHAR2 字符串;NUMBER(1 表示純數字,0 表示非數字);CREATE OR REPLACE FUNCTION isnum(p_str IN VARCHAR2) RETURN NUMBER IS
v_num NUMBER;
BEGIN
-- 去除首尾空格
v_num := TO_NUMBER(TRIM(p_str));
RETURN 1;
EXCEPTION
WHEN VALUE_ERROR THEN
RETURN 0;
WHEN OTHERS THEN
RETURN 0;
END isnum;
/
SHOW ERRORS
TO_NUMBER 不自動去空格);VALUE_ERROR 專門捕獲格式錯誤,OTHERS 兜底,確保函數永不拋出異常;CASE WHEN 或 DECODE。INSERT INTO target_table (id, amount)
SELECT src_id,
CASE WHEN isnum(src_amt) = 1 THEN TO_NUMBER(TRIM(src_amt)) ELSE NULL END
FROM source_table;
ALTER TABLE staging_table ADD CONSTRAINT chk_amt_num CHECK (isnum(amt) = 1);
SELECT isnum(amt) AS is_numeric, COUNT(*) FROM source_table GROUP BY isnum(amt);
若需判斷「整數」、「兩位小數」等特定格式,可擴展參數:
CREATE OR REPLACE FUNCTION isnum_adv(
p_str IN VARCHAR2,
p_fmt IN VARCHAR2 DEFAULT '9999999999D99' -- 默認整數+兩位小數
) RETURN NUMBER IS
v_num NUMBER;
BEGIN
v_num := TO_NUMBER(TRIM(p_str), p_fmt);
RETURN 1;
EXCEPTION WHEN OTHERS THEN RETURN 0; END;
TO_NUMBER 依賴會話級 NLS_NUMERIC_CHARACTERS,跨環境部署時建議顯式指定格式模板;REGEXP_LIKE(str, '^[+-]?\d+(\.\d+)?$') 避免行級函數調用開銷;COMMON_FUNCS),配合 GRANT EXECUTE 實現多用戶共享(詳見上篇)。ISNUM 是數據清洗工具箱中的「瑞士軍刀」,以極簡代碼解決「髒數據入庫」的經典痛點。掌握其原理與擴展方式,能顯著提升 ETL 流程的穩健性與可維護性。