truncate 是 ddl 语句而非函数,不能用于 where;截断数值用 truncate(value, decimals) 函数,清空表用 truncate table table_name 语句,二者同名易混淆。

TRUNCATE 是函数还是语句?别在 WHERE 里用它
TRUNCATE 在 MySQL 中是**DDL 语句**,不是函数,不能出现在 SELECT、WHERE 或表达式中。常见错误是写成 SELECT TRUNCATE(price, 2) FROM orders —— 这会报错:ERROR 1305 (42000): FUNCTION db.TRUNCATE does not exist。因为 MySQL 没有名为 TRUNCATE 的内置函数;你真正想用的是 TRUNCATE() 函数(注意括号),但它和 DDL 语句同名,极易混淆。
实操建议:
- 截断数值(保留小数位):用
TRUNCATE(<var>value</var>, <var>decimals</var>)函数,比如TRUNCATE(123.456, 2)→123.45 - 清空整张表:用
TRUNCATE TABLE <var>table_name</var>语句,比如TRUNCATE TABLE logs - DDL 的
TRUNCATE TABLE会重置自增 ID、不可回滚、不走 binlog(取决于引擎和配置),和DELETE FROM完全不同
TRUNCATE() 函数和 ROUND()、FLOOR() 的关键区别
TRUNCATE() 是「砍掉」,不是「四舍五入」或「向下取整」。它只按位数截断,不改变符号方向,也不进位。
实操建议:
-
TRUNCATE(3.999, 0)→3(不是 4) -
TRUNCATE(-3.999, 0)→-3(不是 -4,也不像FLOOR()那样向下) -
ROUND(3.5, 0)→4,FLOOR(3.9)→3,但TRUNCATE(3.5, 0)→3 - 小数位为负时也有效:
TRUNCATE(1234.56, -2)→1200(截到百位)
TRUNCATE() 在 GROUP BY 或 ORDER BY 中的精度陷阱
直接对浮点字段(如 DECIMAL(10,6) 或 FLOAT)做 TRUNCATE() 分组,可能因隐式类型转换导致意外分组结果。MySQL 会在比较前把截断结果转成浮点,而浮点表示不精确。
实操建议:
- 优先在定义列时用
DECIMAL,避免用FLOAT存金额或需要精确截断的值 - 若必须分组,显式转成字符串再截断更稳妥:
TRUNCATE(CAST(amount AS DECIMAL(12,2)), 2) - 注意
TRUNCATE()返回类型:输入是DECIMAL则返回DECIMAL,输入是DOUBLE则返回DOUBLE,后者可能引入浮点误差
为什么 TRUNCATE TABLE 有时比 DELETE 快,有时反而卡住?
TRUNCATE TABLE 本质是「删表重建」,不逐行扫描,所以通常极快。但它需要独占元数据锁(MDL),且在某些场景下会阻塞或被阻塞。
实操建议:
- 事务中执行
TRUNCATE TABLE会隐式提交当前事务,无法回滚 —— 这点常被忽略 - 如果表上有外键引用,
TRUNCATE TABLE会失败(ERROR 1701 (HY000)),而DELETE FROM不受此限 - InnoDB 表启用
innodb_file_per_table=OFF时,TRUNCATE可能触发整个共享表空间收缩,反而变慢 - 高并发写入场景下,
TRUNCATE等待 MDL 锁的时间可能比大表DELETE更长
最易被忽略的一点:TRUNCATE() 函数对 NULL 值返回 NULL,但不会报错;而 TRUNCATE TABLE 对只读实例或从库会直接拒绝执行——权限和复制角色必须提前确认。











