TO_TIMESTAMP不支持微秒,仅限毫秒;需用TO_TIMESTAMP_TZ(配FF6及时区)或TIMESTAMP字面量(如TIMESTAMP '2024-03-15 10:20:30.123456')实现微秒级精度。

TO_TIMESTAMP 无法直接处理微秒,必须用 TO_TIMESTAMP_TZ 或 TIMESTAMP 字面量
Oracle 19c 的 TO_TIMESTAMP 函数最多只支持到毫秒(三位小数),传入带六位微秒(如 '2024-03-15 10:20:30.123456')的字符串会报错 ORA-01830: date format picture ends before converting entire input string。这不是 bug,是函数设计限制——它没有微秒精度解析能力。
真正能原生支持微秒的是 TO_TIMESTAMP_TZ(配合时区信息)或更推荐的 TIMESTAMP 字面量写法:
-
TO_TIMESTAMP_TZ('2024-03-15 10:20:30.123456 +00:00', 'YYYY-MM-DD HH24:MI:SS.FF6 TZR')—— 需显式指定FF6和时区格式 -
TIMESTAMP '2024-03-15 10:20:30.123456'—— 最简洁、无歧义、自动识别微秒,且不依赖 NLS 设置
用 TIMESTAMP 字面量替代 TO_TIMESTAMP 是最稳的选择
只要字符串格式固定为 YYYY-MM-DD HH24:MI:SS.FF6(如 '2024-03-15 10:20:30.123456'),直接用 TIMESTAMP 字面量即可,无需函数调用,也不受 NLS_DATE_FORMAT 影响。
示例:
SELECT TIMESTAMP '2024-03-15 10:20:30.123456' AS ts FROM DUAL;
返回类型是 TIMESTAMP(6),微秒完整保留。如果源数据来自字符串字段(如 VARCHAR2),可结合 TO_TIMESTAMP_TZ 或先截断再拼接:
- 若确定无时区且需动态转换:
TO_TIMESTAMP_TZ(col || ' +00:00', 'YYYY-MM-DD HH24:MI:SS.FF6 TZR') - 若只想取前六位小数且忽略时区:
TO_TIMESTAMP(SUBSTR(col, 1, 26), 'YYYY-MM-DD HH24:MI:SS.FF3')—— 注意:这会丢弃后三位微秒
FF6 格式符只在 TO_TIMESTAMP_TZ / TO_TIMESTAMP 中生效,且必须匹配输入长度
FF6 表示“最多六位小数秒”,但它不是万能补零开关。如果输入字符串只有三位(如 '10:20:30.123'),用 FF6 不会自动补零;如果输入有六位但格式掩码只写 FF3,就会截断或报错。
常见翻车点:
- 写
TO_TIMESTAMP('2024-03-15 10:20:30.123456', 'YYYY-MM-DD HH24:MI:SS.FF6')→ 报错,因为TO_TIMESTAMP不支持FFn - 写
TO_TIMESTAMP_TZ('2024-03-15 10:20:30.123456', 'YYYY-MM-DD HH24:MI:SS.FF6')→ 报错,缺时区部分(TZR或OF) - 写
TO_TIMESTAMP_TZ('2024-03-15 10:20:30.123456 UTC', 'YYYY-MM-DD HH24:MI:SS.FF6 TZR')→ 成功,UTC被识别为时区名
微秒精度在 INSERT / WHERE 中的实际影响
即使成功转成 TIMESTAMP(6),也要注意 Oracle 对微秒的存储和比较行为:
- 列定义为
TIMESTAMP(6)才能存全六位;定义为TIMESTAMP(3)会四舍五入截断 - 在
WHERE条件中用=比较微秒值时,必须完全一致;用BETWEEN更安全,例如:ts BETWEEN TIMESTAMP '2024-03-15 10:20:30.123456' AND TIMESTAMP '2024-03-15 10:20:30.123456' - 函数索引(如基于
TRUNC(ts, 'HH'))对微秒字段无效,除非显式包含精度参数
微秒级时间通常用于高并发日志或金融交易场景,这时候别只盯着转换函数——列定义、索引策略、绑定变量精度(JDBC 的 setTimestamp(..., Calendar) 默认可能丢微秒)才是更常出问题的地方。











