CEIL返回≥x的最小整数,FLOOR返回≤x的最大整数;二者按无穷方向取整而非四舍五入,负数时易误判,且不改变数据类型,浮点运算需防精度误差。

CEIL 和 FLOOR 函数到底怎么用
SQL 里 CEIL 向上取整、FLOOR 向下取整,不是四舍五入,也不是截断小数——它们只看数值方向,不看小数位大小。比如 CEIL(-2.1) 是 -2(往正无穷方向),FLOOR(-2.1) 是 -3(往负无穷方向)。这点和很多人的直觉相反,尤其在处理负数时容易出错。
实操建议:
-
CEIL(x)返回 ≥ x 的最小整数;FLOOR(x)返回 ≤ x 的最大整数 - 多数数据库(PostgreSQL、Oracle、MySQL 5.7+、SQL Server 2022+)都支持这两个函数,但 SQLite 默认不支持,需手动实现或升级到 3.35+
- 输入为 NULL 时,结果也是 NULL,别指望它自动跳过
- 如果字段是字符串类型(如
'3.7'),部分数据库会隐式转数字,但 Oracle 会直接报错ORA-01722: invalid number
为什么 ROUND 不等于 CEIL/FLOOR
ROUND 是按指定精度四舍五入,而 CEIL/FLOOR 是无条件朝固定方向“跳”到最近整数。例如对 2.5:ROUND(2.5) 在多数数据库中是 3,但 CEIL(2.5) 一定是 3,FLOOR(2.5) 一定是 2;对 -2.5:ROUND(-2.5) 可能是 -2 或 -3(取决于数据库的舍入规则),但 CEIL(-2.5) 永远是 -2,FLOOR(-2.5) 永远是 -3。
常见错误现象:
- 用
ROUND(x, 0)替代CEIL(x)处理价格向上取整(比如运费计算),结果在 0.5 边界处不符合业务要求 - 在分页计算总页数时写成
ROUND(total / size, 0),导致 99 条数据 / 每页 10 条算出 10 页(正确),但 101 条却算成 10 页(错误,应为 11 页)——这里必须用CEIL(total * 1.0 / size)
跨数据库兼容性要注意什么
函数名基本统一,但行为细节有坑。PostgreSQL 和 Oracle 对 CEIL/FLOOR 完全一致;MySQL 早期版本(5.6 及以前)没有 CEIL,只有 CEILING(二者等价),而 FLOOR 一直存在;SQL Server 直到 2022 才原生支持 CEILING(注意拼写是 CEILING,不是 CEIL),旧版本只能用 ROUND(x, 0, 1) 模拟 FLOOR,或 ROUND(x, 0, 0) 加判断模拟 CEILING。
实操建议:
- 写可移植 SQL 时,优先用
CEILING(更老标准)和FLOOR,避免CEIL - MySQL 用户注意:5.7+ 支持
CEIL,但某些云厂商的低版本 RDS 可能仍卡在 5.6,上线前务必验证 - SQL Server 用户若无法升级,可用
CASE WHEN x > 0 THEN FLOOR(x) ELSE CEILING(x) END绕过缺失函数(但性能略差)
浮点精度导致的结果偏差
看似简单的 FLOOR(1.1 + 2.2),在某些数据库(尤其是底层用 double 表示的)可能返回 3 而不是预期的 4,因为 1.1 + 2.2 实际存储为 3.3000000000000003 或 3.2999999999999998,FLOOR 会严格向下取整。
使用场景提示:
- 涉及金额、计数等精确场景,别直接对浮点运算结果用
FLOOR/CEIL - 先用
ROUND(x, 10)截断浮点误差再取整,或改用定点数类型(如 PostgreSQL 的NUMERIC、MySQL 的DECIMAL)参与运算 - PostgreSQL 中
FLOOR(1.1::NUMERIC + 2.2::NUMERIC)稳定返回 3,但FLOOR(1.1 + 2.2)可能不稳定
最常被忽略的是:这些函数本身不改变数据类型,FLOOR(3.0) 返回的仍是 numeric/float 类型,不是 integer——如果后续要和整型字段比较或做聚合,可能触发隐式转换或索引失效。










