ROUND函数语法为ROUND(number, decimals),number为数值表达式,decimals为整数位数(正数保留小数、0取整、负数向左舍入),但行为因数据库而异:MySQL和SQL Server默认四舍五入,PostgreSQL标准一致,SQLite不支持负数位;decimals须为常量,不可为NULL或列名。

ROUND函数的基本用法和参数含义
ROUND 在 SQL 中不是万能四舍五入工具,它的行为取决于数据库系统,而且第二个参数(小数位数)必须是整数常量或表达式,不能是列名或 NULL。多数主流数据库(PostgreSQL、SQL Server、MySQL 5.7+、Oracle)支持 ROUND(numeric_expression, decimal_places),但 SQLite 的 ROUND 只接受两个参数且不支持负数位数,而 MySQL 8.0+ 开始支持负数位(如 ROUND(1234.56, -2) 得到 1200)。
常见错误是传入字符串或未转类型的字段,比如 ROUND('12.345', 2) 在 PostgreSQL 会报错,必须先 CAST('12.345' AS numeric);在 MySQL 中虽可能隐式转换,但不可靠。
- 小数位数为正:保留指定位数,如
ROUND(12.345, 2)→12.35 - 小数位数为 0:四舍五入到整数,如
ROUND(12.7, 0)→13 - 小数位数为负:向左舍入,如
ROUND(1234.56, -1)→1230(注意:SQLite 不支持此用法)
不同数据库对ROUND的兼容性差异
同一个 ROUND 写法,在 PostgreSQL 和 SQL Server 中结果一致,但在 MySQL 中可能因版本和 SQL 模式产生偏差。例如开启 MODE=STRICT_TRANS_TABLES 时,ROUND(NULL, 2) 返回 NULL;而某些旧版 MySQL 在遇到浮点精度问题时,ROUND(2.5, 0) 可能返回 2(银行家舍入),实际取决于 SELECT @@version_compile_os 和服务器配置。
如果你在跨库迁移或写通用脚本,不要依赖 ROUND 的“标准行为”。更稳妥的做法是:明确指定类型 + 使用 CAST 或 CONVERT 预处理,尤其当源字段是 float 或 real 类型时。
- PostgreSQL 推荐:
ROUND(CAST(price AS numeric), 2) - SQL Server 推荐:
ROUND(CAST(price AS decimal(18,4)), 2) - MySQL 8.0+ 可用:
ROUND(price + 0.0, 2)强制转为 double,避免整型截断
ROUND在SELECT中结合别名和NULL值的处理
直接在 SELECT 中用 ROUND(column_name, 2) 是最常见场景,但要注意:如果该列允许 NULL,ROUND(NULL, 2) 结果仍是 NULL,不会报错,也不会变成 0 —— 这一点常被忽略,导致前端展示空值却以为是计算失败。
若业务要求 NULL 显示为 0.00,得显式处理,不能只靠 ROUND。另外,别名命名建议避开 round 这类关键字(尤其在 PostgreSQL 中,虽然不报错,但可能干扰语法高亮或 ORM 解析)。
- 安全写法:
SELECT ROUND(COALESCE(amount, 0), 2) AS amount_rounded FROM orders - 避免写成:
SELECT ROUND(amount, 2) AS round FROM ...(round是保留字,部分客户端会警告) - 注意:MySQL 中
ROUND对 DECIMAL 类型更稳定,对 FLOAT 类型可能因二进制表示误差导致意外结果,例如ROUND(1.235, 2)有时返回1.23而非1.24
替代方案:当ROUND不够用时考虑什么
如果需要固定格式输出(如总是显示两位小数,含末尾 0),ROUND 本身做不到 —— 它只做数值运算,不控制显示格式。这时候得配合类型转换或字符串函数,比如 PostgreSQL 用 TO_CHAR(amount, 'FM999999990.00'),SQL Server 用 FORMAT(amount, 'N2')(但性能较差),MySQL 则常用 CONCAT(ROUND(amount, 2), '0') 加兜底(不推荐,易出错)。
另一个典型坑是聚合后四舍五入:ROUND(AVG(score), 2) 和 AVG(ROUND(score, 2)) 数学意义完全不同,前者先算均值再舍入,后者先逐条舍入再平均,误差可能累积。
- 正确做法(推荐):
ROUND(AVG(score), 2) AS avg_score - 错误直觉:
AVG(ROUND(score, 2))—— 会放大舍入偏差 - 如需绝对可控精度,考虑在应用层做 final rounding,数据库只传原始值
ROUND 很容易“看起来没问题,其实结果不对”。

















