SQL Server ROUND()函数处理含第三位小数5的float值异常行为问询
问题原因解析
你遇到的ROUND函数计算结果不一致的问题,核心原因是float属于近似数值存储类型,无法精确存储所有十进制小数。
你看到的三位小数为5的数值(比如0.165)只是查询展示时的近似值,实际磁盘存储的二进制值可能存在极微偏差:
- 若实际存储值略小于0.165(比如0.16499999999999998),ROUND保留两位小数时会舍去得到0.16
- 若实际存储值略大于0.165(比如0.16500000000000001),ROUND保留两位小数时会进位得到0.17
修复方案
- 长期方案:价格类涉及精度计算的字段,建议改成
DECIMAL/NUMERIC这类精确数值类型存储,从根源避免精度丢失问题 - 临时兼容方案:不修改表结构的前提下,ROUND计算前先将float值显式转换为固定精度的精确类型,即可得到符合预期的四舍五入结果,优化后的查询语句如下:
SELECT CODE, FWHSPRICE, RTLPRICE, ISNULL(NULLIF(FWHSPRICE, 0), RTLPRICE) AS REGULAR, ROUND(CAST(FLDFLOAT3 AS DECIMAL(18,3)), 2) AS SALE FROM MATERIAL WHERE COMID = 12 AND FLTID1 = 1
SSMS导出测试数据INSERT语句步骤
- 打开SSMS连接到目标数据库,在数据库名称上右键选择「任务」→「生成脚本」
- 向导页点击下一步,选择「选择特定数据库对象」,找到
MATERIAL表勾选后点击下一步 - 点击「高级」按钮,在弹出的设置窗口中:
- 找到「要编写脚本的数据的类型」,选择「仅数据」(需要表结构的话可以选「架构和数据」)
- 按需调整筛选规则,确认后点击确定
- 选择输出到新查询窗口或者本地文件,点击下一步完成即可生成INSERT语句,你可以自行筛选保留少量可复现问题的测试数据即可。
内容的提问来源于stack exchange,提问作者Faye D.
相关产品推荐
相关产品推荐

