Oracle查询返回9999.99999999999而非10000的根因及异常插入原因
精度偏差根本原因
- 核心是二进制浮点类型转十进制数值的固有误差累加:2012年数据插入时,上游应用大概率使用了
double/float这类二进制浮点类型存储金额。0.11这类十进制小数无法被二进制浮点数精确表示,会自带极微小的尾数位误差(例如0.11实际会被存储为接近0.11的近似值0.110000000000000000208...),这类误差在插入Oracle的NUMBER字段时被完整保留,你查询到的17910295.110000001就是这类转换误差的直观体现。 - 多笔带微小尾差的数值经过窗口函数
SUM累加后,误差被逐步放大,最终累积出-1E-9的总差值,导致计算结果为9999.99999999999而非预期的10000。Oracle的NUMBER类型本身是十进制精确存储的,但不会主动修正输入源本身携带的精度误差,计算过程也会完整保留所有尾数位。
异常尾数位数值可插入的原因
- 表DDL中
AMT_TXN字段定义为无精度约束的NUMBER类型:无约束的Oracle NUMBER类型支持存储最大精度38位的合法十进制数值,只要输入值属于合法数值范围,哪怕带有极微小的尾数位误差,也不会被自动截断或触发插入报错。如果字段定义为明确精度的NUMBER(p,2)这类格式,写入时会自动截断超出2位小数的部分,就不会出现这类异常尾数。 - 现有CHECK约束仅校验
COD_DRCR的取值范围,未对AMT_TXN的精度做任何限制,也允许这类带尾差的数值正常写入。你提到的ENABLE NOVALIDATE是COD_DRCR约束的属性,和金额字段的插入逻辑无关。
内容的提问来源于stack exchange,提问作者May
相关产品推荐
相关产品推荐

