postgresql的round()默认是算术四舍五入(非银行家舍入),如round(2.5,0)得3;但浮点类型可能因ieee 754精度失真导致错误结果,应强制转numeric,如round(1.005::numeric,2)。

PostgreSQL 中没有 ROUND() 以外的内置“四舍五入到指定精度”函数,但它的 ROUND() 行为就是标准四舍五入(银行家舍入?不,不是——PostgreSQL 的 ROUND() 是算术四舍五入)。
ROUND() 函数怎么用才真正四舍五入?
PostgreSQL 的 ROUND(numeric, int) 默认就是按数学规则四舍五入,比如 ROUND(2.5) 得 3,ROUND(3.5) 得 4,ROUND(1.234, 2) 得 1.23。
注意:它对 numeric 和 double precision 都有效,但浮点类型可能因精度问题导致意外结果(比如 ROUND(1.005::double precision, 2) 可能返回 1.0 而非 1.01)。
- 始终优先把输入转成
numeric:用::numeric强制转换,例如ROUND(1.005::numeric, 2) - 小数位数为负时,表示向左舍入:
ROUND(123.456, -1)→120 - 省略第二参数等价于
ROUND(x, 0),即取整到个位
为什么有时候 ROUND() 看起来“没四舍五入”?
常见现象:SELECT ROUND(1.005::double precision, 2); 返回 1.0,而不是预期的 1.01。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
原因:IEEE 754 浮点表示下,1.005 无法被精确存储,实际值可能是 1.0049999999999999,再四舍五入就变成 1.00。
- 解决办法:显式转
numeric,如ROUND('1.005'::numeric, 2)或ROUND(1.005::numeric, 2) - 字符串字面量转
numeric更可靠,因为不会经过浮点解析阶段 - 如果数据来自浮点列(如
float8),先CAST(col AS numeric)再ROUND()
需要截断(truncation)而非四舍五入时怎么办?
别误用 ROUND()。PostgreSQL 提供 TRUNC() 函数做直接截断:
-
TRUNC(3.7)→3 -
TRUNC(-3.7)→-3(向零取整) -
TRUNC(1.234, 2)→1.23 - 和
ROUND()一样,也建议输入为numeric类型以避免浮点误差
性能与类型隐式转换的坑
在 WHERE 或 ORDER BY 中频繁用 ROUND(col, 2) 可能导致索引失效,尤其当 col 是 double precision 且未建函数索引时。
- 若需按四舍五入后值高效查询,考虑建函数索引:
CREATE INDEX idx_rounded ON tbl (ROUND(amount::numeric, 2)); - 避免在条件中写
ROUND(col::double precision, 2) = 1.23,应改为范围查询或确保类型一致 -
numeric运算比double precision稍慢,但精度可控;金融类场景必须用numeric
最常被忽略的一点:四舍五入逻辑是否真的该在数据库层做?如果应用层已持有原始值,且仅用于展示,那交给前端或应用处理更灵活;只有当聚合、比较、或写回数据库时才需要 SQL 层精确四舍五入。










