round是四舍五入,trunc是直接截断不进位;二者精度参数行为一致,但语义不同:round可能改变数值方向,trunc恒向零截断,财务等确定性场景须慎选。

ROUND 和 TRUNC 都能截断小数位,但 ROUND 是四舍五入,TRUNC 是直接截断(不进位);用错函数或忽略精度参数会导致结果偏差,尤其在财务计算中容易出错。
ROUND(value, precision) 的行为与常见误用
ROUND 对浮点数按指定小数位数执行四舍五入,但要注意:不同数据库对负数的处理略有差异(如 PostgreSQL 与 Oracle 在 -1.5 上的结果一致,但某些旧版 MySQL 可能有舍入策略差异)。
-
precision为正数时,保留对应小数位:ROUND(3.14159, 2)→3.14 -
precision为 0 时,四舍五入到整数:ROUND(3.7, 0)→4 -
precision为负数时,向左舍入(十位、百位等):ROUND(1234.56, -2)→1200 - 省略
precision默认为 0,但显式写出更安全,避免跨库迁移时行为不一致 - 浮点数本身精度问题可能干扰结果,例如
ROUND(2.675, 2)在某些系统中返回2.67而非2.68(因 2.675 实际存储为略小于它的二进制近似值)
TRUNC(value, precision) 不进位截断的典型用途
TRUNC 常用于需要“向下取整到某一位”而非四舍五入的场景,比如计算折扣后价格上限、日志采样周期对齐、或规避浮点舍入误差影响。
-
TRUNC(3.14159, 2)→3.14(不是四舍五入,是硬截) -
TRUNC(-3.9, 0)→-3(注意:它不是 floor,对负数是向零截断) -
TRUNC(1234.56, -1)→1230(截掉个位,不看后面数字) - PostgreSQL 中函数名是
TRUNC,MySQL 和 Oracle 也是,但 SQLite 不支持该函数,需用CAST(value AS INTEGER)或FLOOR替代(功能不完全等价)
ROUND vs TRUNC:关键区别与选型依据
二者核心差异不在“是否保留小数”,而在于“是否引入舍入逻辑”。这直接影响业务语义——比如统计平均单价时用 ROUND 更合理,而计算可发放积分(按元取整但不额外赠送)则必须用 TRUNC。
- ROUND 可能改变数值方向(如 2.5 → 3),TRUNC 永远不增加绝对值
- 当
precision相同且输入为正数时,TRUNC 结果 ≤ ROUND 结果;负数时需单独验证(如TRUNC(-2.7, 0) = -2,ROUND(-2.7, 0) = -3) - 性能上无显著差异,但 TRUNC 更少引发意外进位,适合确定性要求高的批处理
- 某些数据库(如 SQL Server)的
ROUND支持第三个参数(function),设为 1 可模拟 TRUNC 行为:ROUND(x, 2, 1)≈TRUNC(x, 2)
浮点数精度陷阱与绕过建议
直接对 DOUBLE 或 REAL 类型字段用 ROUND/TRUNC,可能因底层二进制表示导致预期外结果。例如 0.1 + 0.2 在多数数据库中不精确等于 0.3。
- 涉及金额等关键数值,优先使用
DECIMAL(p,s)类型存储,再进行 ROUND/TRUNC - 若只能处理浮点列,先用
ROUND(value, 12)消除微小误差,再做主逻辑(12 是经验位数,覆盖 double 精度) - 测试时务必覆盖边界值:0.005、-0.005、9.995、-9.995,观察是否符合业务定义的“四舍”或“截断”
- 跨数据库迁移前,用相同数据集对比各平台的
ROUND(0.5, 0)和TRUNC(-0.5, 0)输出,确认语义一致
真正难的不是调用哪个函数,而是明确业务里“保留两位小数”到底指“银行家舍入”“向上取整”还是“砍掉不要”,以及是否允许浮点中间态参与计算。










