TO_CHAR 是 Oracle 將數值/日期轉為字串的核心函數,格式模板極其豐富。本文系統整理**數值格式化參數、日期格式參數、FM 去除前導零/空白、小數位精確控制、四捨五入行為、NULL 判斷陷阱**、並提供可直接複製的實戰範本。
數值格式化核心參數
| 符號 | 含義 | 範例輸入 | 輸出 |
| 9 | 數字位 (不足不補零) | TO_CHAR(1210.73, '9999.9') | 1210.7 |
| 0 | 數字位 (不足補零) | TO_CHAR(21, '000099') | 000021 |
| , | 千分位分隔 | TO_CHAR(1210.73, '9,999.99') | 1,210.73 |
| . | 小數點 | TO_CHAR(1210.73, '$9,999.00') | $1,210.73 |
| $ | 貨幣符號 | TO_CHAR(1210.73, '$9,999.00') | $1,210.73 |
| FM | **去除前導/尾隨空白與零** | TO_CHAR(1.12, 'FM90.0999') | 1.12 (無空白) |
| B | 零值顯示空白 | TO_CHAR(0, 'B999') | (空白) |
| MI | 負號後置 | TO_CHAR(-100, '999MI') | 100- |
| PR | 負數括號 | TO_CHAR(-100, '999PR') | <100> |
日期格式化核心參數
| 參數 | 含義 | 範例 |
| YYYY / YY / Y | 4/2/1 位年份 | 2024 / 24 / 4 |
| MM / MON / MONTH | 月份數字 / 縮寫 / 全名 | 07 / JUL / JULY |
| DD / DDD | 月內天 / 年內天 | 09 / 191 |
| DAY / DY | 星期全名 / 縮寫 | TUESDAY / TUE |
| HH24 / HH12 | 24/12 小時制 | 14 / 02 |
| MI / SS / SSSSS | 分 / 秒 / 午夜秒數 | 30 / 59 / 51839 |
| Q / WW / IW | 季度 / 年週數 / ISO 週數 | 3 / 28 / 27 |
| RM | 羅馬數字月份 | VII |
| J | 儒略日 | 2459000 |
日期範例速查
TO_CHAR(SYSDATE, 'YYYY/MM/DD') -- 2024/07/09
TO_CHAR(SYSDATE, 'Month DD, YYYY') -- July 09, 2024
TO_CHAR(SYSDATE, 'FMMonth DD, YYYY') -- July 9, 2024 (去零)
TO_CHAR(SYSDATE, 'MON DDth, YYYY') -- JUL 09TH, 2024
TO_CHAR(SYSDATE, 'FMMON DDth, YYYY') -- JUL 9TH, 2024
TO_CHAR(SYSDATE, 'FMMon ddth, YYYY') -- Jul 9th, 2024
實戰需求:小數點最多 4 位、最少 2 位、去空白、四捨五入
-- 1.00、1.10、1.12、1.1234、1.1235 (1.12345→1.1235)
SELECT TO_CHAR(123.0233, 'FM9999999.0099') FROM DUAL;
-- FM : 去空白
-- 9999999 : 整數部最多 7 位
-- .00 : 強制 2 位小數 (不足補零)
-- 99 : 額外允許 2 位 (共 4 位),第 5 位四捨五入
常見陷阱與對策
| 陷阱 | 現象 | 對策 |
| 小數前導零消失 | TO_CHAR(0.123) → .123 | 用 TO_CHAR(0.123, '0.999') 或 FM0.0099 |
| 整數顯示多餘小數點 | TO_CHAR(100, 'FM90.0999') → 100. | 自寫函數移除尾隨 .,或用 CASE WHEN TRUNC(n)=n THEN TO_CHAR(n) ELSE TO_CHAR(n,'FM999.0099') END |
| 四捨五入非截斷 | TO_CHAR(1.999, '9.99') → 2.00 | 需截斷請自寫 TRUNC(n, 2) 再格式化 |
| 日期轉數值再格式化 | 需先 TO_NUMBER(TO_CHAR(dt,'J')) 再 TO_CHAR | 直接用日期格式模板更簡潔 |
| SELECT INTO 空/多行報錯 | NO_DATA_FOUND / TOO_MANY_ROWS | 改用游標或 MAX() 聚合保證單行 |
| ROWNUM 不支援排序 | WHERE ROWNUM=2 永無結果 | 用子查詢 + ROW_NUMBER() |
| NULL 判斷失效 | var = NULL 永遠 UNKNOWN | 用 var IS NULL 或 NVL(var, 'default') |
| 參數名衝突欄位名 | 存儲過程參數同名表欄位 → 解析為欄位 | 參數加前綴 p_/v_ |
進階:NLS 參數控制貨幣/小數點符號
TO_CHAR(17145, 'L099G999', 'NLS_NUMERIC_CHARACTERS='',.'' NLS_CURRENCY=''NTD''')
-- 結果:NTD017,145
-- L: 本地貨幣符號 (由 NLS_CURRENCY 決定)
-- G: 群組分隔符 (由 NLS_NUMERIC_CHARACTERS 第二字元決定)
-- .: 小數點 (由 NLS_NUMERIC_CHARACTERS 第一字元決定)
最佳實務清單
- **顯式指定格式模板**,不依賴隱性
NLS_TERRITORY。
- **報表/匯出** 全程使用
FM 去除對齊空白。
- **金融金額** 必須
TRUNC(value, 2) 截斷後再 TO_CHAR,避免四捨五入差異。
- **多語系系統** 統一用
NLS_NUMERIC_CHARACTERS、NLS_CURRENCY 參數覆蓋。
- **PL/SQL 參數命名** 統一
p_ (IN)、v_ (區域變數) 前綴,避免欄位名衝突。
精通 TO_CHAR 格式模板與陷阱,能讓報表輸出、介面顯示、資料匯出一次到位,減少前端二次處理與溝通成本。