SQL 插入小数后精度丢失怎么办
时间:2026-08-23 | 作者:怪兽小助手 | 阅读:0导致问题的根本原因是精度丢失,并非数据损坏。具体来说,SQL Server的money字段因JDBC驱动忽略scale,MySQL变量未声明精度,MyBatis批量插入时取最小scale,PostgreSQL/Oracle误用浮点类型,这些情况都会致使小数位被截断或计算出现失准的现象。
直接原因通常是数据库字段类型没配对、JDBC驱动没传精度、或者SQL里写了裸数字触发隐式转换——不是数据“坏了”,而是中间某一层悄悄把它当整数或浮点数处理了。
SQL Server 插入时 money 字段丢小数位
SQL Server的money类型比较特殊,它本质上是固定的DECIMAL(19,4)。然而,JDBC驱动(尤其是旧版本)并不认识这个类型。当使用setBigDecimal方法时,它会直接忽略scale参数。因此,BigDecimal(35.35, scale=2)会被当作35插入到数据库中。
- 临时解法:改用标准
DECIMAL(p,s)字段,比如DECIMAL(18,2) - 驱动层补救:升级
mssql-jdbc到 9.4+,连接串加参数calcBigDecimalPrecision=true - MyBatis 显式声明:在 XML 中给参数加
jdbcType=DECIMAL和numericScale=2,例如#{item.amount, jdbcType=DECIMAL, numericScale=2} - 绕过驱动:SQL 层强制 cast,如
cast(#{item.amount} as decimal(18,2))—— 这招在批量插入时最稳
MySQL 存储过程/函数里小数计算失准
哪怕字段定义是 DECIMAL(15,2),只要函数里用了 DECLARE total DECIMAL; 或调用时传 100 而不是 100.0,MySQL 就会按 DOUBLE 解析,中间一算就漂移。
- 变量声明必须带精度:写成
DECLARE amount DECIMAL(15,2);,不能省略(M,D) - 调用时字面量加
.0:用CALL calc(100.0, 0.08);替代CALL calc(100, 0.08); - 运算链全程保 DECIMAL:所有参与计算的值都显式
CAST(... AS DECIMAL(15,2)),别依赖自动推导 - 注意
SUM()默认返回DECIMAL(10,0):要精度就得SUM(CAST(amount AS DECIMAL(15,2)))
MyBatis 批量插入时统一截断
MyBatis 对同一批参数会取最小公因数式精度——如果列表里有个 amount=100(scale=0)、另一个 amount=99.99(scale=2),驱动可能全按 scale=0 处理,导致后者变 99。
- XML 中每个数值参数都加
jdbcType和numericScale,不靠默认映射 - 更彻底:在 SQL 层 cast,例如
cast(#{item.gljyje} as decimal(22,6)),把精度控制收在 SQL 里 - 避免混用:列表里别掺整数和小数,统一转成带小数位的
BigDecimal再传 - 验证手段:开启 MyBatis
STDOUT_LOGGING,看日志里 bind 的参数是否带 scale 信息
PostgreSQL / Oracle 的 REAL/DIRECTIVE 类型陷阱
REAL 和 DOUBLE PRECISION 是 IEEE 754 浮点,0.1 + 0.2 存进去就是 0.30000000000000004,这不是 bug,是设计如此。
- 财务、计费、配置类字段,一律用
NUMERIC(p,s)或NUMBER(p,s),别碰FLOAT系列 - 已有
REAL字段?别指望修数据,得改表结构:ALTER TABLE t ALTER COLUMN col TYPE NUMERIC(12,4) USING col::NUMERIC(12,4); - BI 工具里看到的“对不上”,先查数据库原值:
SELECT col::TEXT FROM t,如果文本显示19.999999,说明存储层已失真 - 应用层接收时,Ja va 用
BigDecimal,Python 用decimal.Decimal,别用float
真正容易被忽略的,是那个没加 .0 的除数、那个没声明标度的 DECIMAL 变量、还有 MyBatis 里没显式写的 numericScale——它们不会报错,只是默默把 35.35 变成 35。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
