oracle date类型不支持毫秒,仅精确到秒;需改用timestamp(6)字段及oracledbtype.timestamp绑定才能保存毫秒精度。

Oracle 的 DATE 类型本身不存毫秒 —— 它只精确到秒,这是根本原因。你用 DateTime.Now 带着毫秒去插,Oracle 驱动(尤其是老版本)会自动截断或四舍五入,不是 C# 传错了,是 Oracle 拒绝收。
Oracle DATE 类型天生不含毫秒
Oracle DATE 是一个“年月日时分秒”固定结构,没有毫秒字段。哪怕你传 2026-08-27 10:23:45.678,Oracle 内部只保留 2026-08-27 10:23:45,后面三位直接丢弃。这不是驱动 bug,是类型契约。
- 验证方法:在 SQL*Plus 中执行
SELECT DUMP(SYSDATE) FROM DUAL,结果末尾始终是 0(表示秒,无小数部分) -
OracleDbType.Date对应的就是这个语义,绑定DateTime时驱动会主动抹掉毫秒 - 别指望
TO_CHAR(col, 'YYYY-MM-DD HH24:MI:SS.FF3')能显出毫秒 —— 它没存,就不可能格式化出来
要用 TIMESTAMP(6) 才能保毫秒
必须改数据库字段类型为 TIMESTAMP(6),同时 C# 端改用 OracleDbType.TimeStamp 绑定。否则毫秒永远进不了库。
- 建表或修改字段:
ALTER TABLE users MODIFY created_time TIMESTAMP(6) - C# 参数绑定不能写
DbType.DateTime,得用OracleDbType.TimeStamp - 确保 Oracle.ManagedDataAccess 版本 ≥ 19.15,否则
DateTimeOffset或微秒解析可能失败 - 如果查出来的值毫秒位仍是
000,检查是不是 SELECT 里又写了裸列 —— 改成CAST(created_time AS TIMESTAMP(6))强制精度
DateTime.Now 插入前就可能已失真
Windows 系统时钟默认分辨率约 15ms,DateTime.Now 连续调用多次很可能返回完全相同的时间戳。你以为传了毫秒,其实底层根本没变。
- 用
Stopwatch.GetTimestamp()+Stopwatch.Frequency可获得更高精度时间源(但注意它不是 wall-clock 时间) - 若业务强依赖毫秒唯一性,不要依赖
DateTime.Now生成主键或事件序号 - Oracle 插入时的
SYSTIMESTAMP比应用层传入更可靠,可考虑让 DB 侧生成时间:INSERT INTO t (ts) VALUES (SYSTIMESTAMP)
最常被忽略的一点:即使字段是 TIMESTAMP(6)、驱动也配对了,如果 SQL 字符串拼接中用了 ToString("yyyy-MM-dd HH:mm:ss") 格式化再传参,毫秒照样没了 —— 字符串路径绕过了类型绑定,直接走 Oracle 默认字符串转时间逻辑,而那个逻辑又默认按 DATE 解析。











