ROUND函数可保留小数位,但MySQL/PostgreSQL默认传统四舍五入,SQL Server/Oracle默认银行家舍入,且浮点精度问题易导致ROUND(1.235,2)等结果偏差,建议先CAST为DECIMAL再使用。

ROUND 函数能保留小数位,但行为因数据库而异——MySQL 和 PostgreSQL 默认四舍五入,SQL Server 和 Oracle 在特定模式下可能截断;直接写 ROUND(x, 2) 不一定得到你想要的“严格四舍五入”结果。
ROUND 在不同数据库中的默认行为差异
同一个 ROUND(1.235, 2),在 MySQL 和 PostgreSQL 中返回 1.24,但在 SQL Server(兼容模式为 120+)或某些 Oracle 配置下可能返回 1.23(银行家舍入或截断逻辑)。这不是 bug,是标准实现选择不同。
- MySQL / PostgreSQL:传统四舍五入(half away from zero)
- SQL Server:默认使用“四舍六入五成双”(banker’s rounding),除非显式用
ROUND(x, 2, 0)强制截断模式 - Oracle:
ROUND是四舍五入,但TRUNC才是截断;注意别和TO_CHAR(..., 'FM990.00')混用,后者是格式化而非数值计算
ROUND 的第二个参数必须是整数,且可为负数
很多人以为 ROUND 只能向右保留小数,其实它也支持向左取整。第二个参数是“小数点后第几位”,负数表示小数点左边的位置。
-
ROUND(1234.56, 2)→1234.56 -
ROUND(1234.56, 0)→1235(四舍五入到个位) -
ROUND(1234.56, -2)→1200(四舍五入到百位) - 传入非整数如
ROUND(x, 1.5)会报错:ERROR: function round(numeric, double precision) does not exist(PostgreSQL)
遇到 .5 时结果不稳定?加偏移量强制四舍五入
当业务明确要求“所有 .5 都向上进位”(比如财务计费),而数据库默认是银行家舍入时,不能依赖 ROUND。更可靠的做法是手动加一个极小值再截断:
SELECT FLOOR(x * 100 + 0.5) / 100.0 AS rounded_2dp FROM t;
等价于“先放大、加 0.5、向下取整、再缩小”。适用于所有 SQL 方言,不依赖 ROUND 实现细节。
- 避免用
ROUND(x + 0.005, 2):浮点误差可能导致1.235 + 0.005 = 1.2399999999999998,最终变成1.23 - 整数倍缩放(如 ×100)比浮点加法更安全
- 如果字段是
DECIMAL类型,优先用CAST配合整数运算,避免隐式转 float
ROUND 不改变字段类型,但可能引发隐式转换问题
对 DECIMAL(10,4) 字段执行 ROUND(col, 2),结果仍是 DECIMAL,但精度可能被数据库重设。例如在 MySQL 8.0 中,ROUND(DECIMAL, 2) 返回 DECIMAL(10,2);而在旧版本中可能退化为 DOUBLE,导致后续比较出错。
- 显式用
CAST(ROUND(x, 2) AS DECIMAL(10,2))控制输出类型 - 在 GROUP BY 或 JOIN 条件中用
ROUND要小心:不同精度的 DECIMAL 值可能无法正确匹配 - WHERE 子句里慎用
ROUND(price, 2) = 19.99,不如写成price BETWEEN 19.985 AND 19.994999...更可靠
真正麻烦的不是怎么写 ROUND,而是你以为它做了什么,其实数据库悄悄换了规则。尤其在跨库迁移或对接报表工具时,ROUND 的行为差异常是精度偏差的隐藏源头。

















