SQL视图中必须用ROUND()实现四舍五入,因其按规则判断进位(如第三位≥5则进1),而TRUNCATE()仅直接截断不判断、不进位,无法满足四舍五入语义。

SQL视图中四舍五入必须用 ROUND(),不能靠 TRUNCATE() 实现——后者只是截断,不进位。
为什么视图里用 ROUND() 才算真正四舍五入
视图本质是保存的查询语句,它不存储数据,只在查询时执行逻辑。所以你在视图定义里写 ROUND(price, 2),每次 SELECT 视图都会实时计算并返回保留两位小数的四舍五入结果;而 TRUNCATE(price, 2) 永远只会砍掉多余位数,比如 TRUNCATE(1.999, 2) 得 1.99,不是 2.00。
-
ROUND()看第三位小数:≥5 就进 1,否则舍去(注意:部分数据库如 PostgreSQL 默认用银行家舍入,MySQL 5.7+ 是传统四舍五入) -
TRUNCATE()不看下一位,直接按位数切,连判断都省了 - 视图字段若需参与后续聚合(如
SUM()或报表展示),用错函数会导致累计误差明显
MySQL 视图中 ROUND() 的常见陷阱
MySQL 的 ROUND() 在整数位处理上容易出人意料,尤其当第二参数为负数时:
-
ROUND(1234.56, -1)→1230(四舍五入到十位) -
ROUND(1235.56, -1)→1240,但ROUND(1235.56, -2)→1200 - 如果字段是
DECIMAL类型且精度不足(如DECIMAL(5,2)),ROUND(x, 3)会先被隐式转成该精度再计算,可能丢失原始小数位 - 视图中嵌套
ROUND()+CAST()容易触发隐式类型转换,建议显式指定目标类型,例如ROUND(price, 2) AS price_rounded,别写成CAST(ROUND(price, 2) AS DECIMAL(10,2))多余包裹
什么时候该用 TRUNCATE() 而不是 ROUND()
只有明确需要“向下截断”逻辑时才选 TRUNCATE(),典型场景包括:
- 计算折扣后价格但要求不向上进位(如满 99 减 10,实际支付取整到元但不四舍五入)
- 导出数据给财务系统,对方要求所有分位一律丢弃(如
TRUNCATE(100.999, 0)→100) - 和某些旧系统对接,其金额字段只支持整数,且协议规定“截断不进位”
- 注意:
TRUNCATE()在 SQLite 中不存在,PostgreSQL 需用TRUNC()(无E),Oracle 和 MySQL 支持TRUNCATE(),函数名不统一,建视图前务必确认目标库语法
视图里数值处理最易被忽略的一点:函数行为依赖底层数据库版本和配置。比如 MySQL 8.0.23+ 对 ROUND() 的浮点数处理更严格,而早期版本对 DOUBLE 字段调用 ROUND() 可能出现意外精度漂移——别只测样例数据,一定要拿边界值(如 .499、.500、.501)在线上环境验证。

















