Oracle 提供顯式轉換函數,避免隱式轉換導致的計畫不穩定、NLS 敏感或效能損耗。
SELECT TO_NUMBER('8897') FROM dual; -- 回傳 8897 (NUMBER)
TO_NUMBER('1,234.56', '9,999.99')。ORA-01722。SELECT TO_CHAR(8897) FROM dual; -- '8897'
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual; -- 日期格式化
SELECT TO_CHAR(12345.67, 'FM99,999.00') FROM dual; -- 數值格式化
YYYY/MM/DD HH24:MI:SS、MONTH、DAY、AM/PM 等。9 (數字)、0 (前導零)、FM (抑制空白)、, . (分隔符)。TO_CHAR(dt, 'fmt', 'NLS_DATE_LANGUAGE=AMERICAN')。SELECT TO_DATE('12-DEC-02') FROM dual; -- 依 NLS_DATE_FORMAT 解析
SELECT TO_DATE('20021227', 'YYYYMMDD') FROM dual; -- 明確格式模型
SELECT TO_DATE('20021236', 'YYYYMMDD') FROM dual; -- ORA-01847: day of month must be between 1 and 31
SELECT TO_DATE('baddate') FROM dual; -- ORA-01861: literal does not match format string
| 場景 | 錯誤做法 | 正確做法 |
|---|---|---|
| WHERE 子句隱式轉換 | WHERE id = '123' (id 為 NUMBER) | WHERE id = 123 或 WHERE TO_CHAR(id) = '123' |
| 日期字面值 | WHERE dt = '2024-01-01' | WHERE dt = DATE '2024-01-01' (ANSI 標準) 或 TO_DATE |
| 跨環境部署 | 依賴 NLS_DATE_FORMAT | 所有 TO_DATE/TO_CHAR 明確指定格式模型 |
| 效能 | 索引欄位包裹函數 TO_CHAR(col) = 'val' | 改寫為 col = TO_DATE('val', 'fmt') 使用索引 |
-- TIMESTAMP WITH TIME ZONE
SELECT TO_TIMESTAMP_TZ('2024-01-01 12:00:00 +08:00', 'YYYY-MM-DD HH24:MI:SS TZH:TZM') FROM dual;
-- 時區轉換
SELECT FROM_TZ(CAST(TO_DATE('2024-01-01 12:00', 'YYYY-MM-DD HH24:MI') AS TIMESTAMP), 'UTC')
AT TIME ZONE 'Asia/Taipei' FROM dual;
顯式轉換、明確格式模型、避免索引欄位函數包裹,是編寫穩定、高效、可移植 SQL 的鐵律。