推荐使用 cast 而非 convert 进行显式类型转换,因 cast 符合 sql 标准、行为稳定;cast 必须用 as 指定合法类型(如 signed、date),不可用 int/float;字符串转数值时非法输入静默返回 0,需前置校验。

MySQL 中 CAST 和 CONVERT 都能做显式类型转换,但 CAST 是 SQL 标准写法、更推荐;CONVERT 是 MySQL 扩展语法,部分场景下行为不一致,容易踩坑。
CAST() 的正确写法与常见报错
CAST 必须用 AS 连接目标类型,且目标类型名必须是 MySQL 官方支持的(如 SIGNED、DECIMAL(10,2)、DATE),不能写 INT 或 FLOAT —— 这些不是合法类型名,会直接报错 Truncated incorrect INTEGER value 或类似提示。
-
CAST('123' AS SIGNED)✅ 合法,转成有符号整数 -
CAST('123' AS INT)❌ 报错,INT 不在 MySQL 类型白名单中 -
CAST('2023-05-01' AS DATE)✅ 合法,格式匹配标准日期 -
CAST('05/01/2023' AS DATE)⚠️ 返回NULL,不报错但结果不可靠 - 字符串开头非数字时转数值:例如
CAST('abc123' AS SIGNED)得0,不是错误,但极易被误判为“转换成功”
CONVERT() 与 CAST() 的关键差异
CONVERT(expr, type) 看似简洁,但实际存在两个隐含陷阱:一是它和 CONVERT(expr USING charset) 重载,解析歧义高;二是某些旧版本 MySQL 对 CONVERT('123.45', DECIMAL) 这类写法支持不一致,而 CAST('123.45' AS DECIMAL(5,2)) 始终明确。
- 想转字符集?必须用
CONVERT(expr USING utf8mb4),CAST 不支持USING - 只是类型转换?统一用
CAST(expr AS type),避免混淆 -
CONVERT('123', SIGNED)在部分 MySQL 5.7 实例中可能被当作函数调用失败,而 CAST 写法稳定
WHERE / ORDER BY 中用 CAST 的性能风险
在过滤或排序时对字段套 CAST,几乎必然导致索引失效。比如 WHERE CAST(phone AS CHAR) LIKE '138%',即使 phone 是 BIGINT 且有索引,执行计划里 key 列也会是 NULL。
- 替代方案:建生成列 + 索引,例如
ALTER TABLE users ADD phone_str VARCHAR(20) STORED AS (CAST(phone AS CHAR)),再对phone_str加索引 - 日期分组优先用
DATE(created_at)而非CAST(created_at AS DATE),前者更易被优化器识别 - 必须临时转换?先用
EXPLAIN确认key和Extra字段,看到Using filesort或Using temporary就得警惕
空值与边界值的处理逻辑
CAST 对 NULL 和空字符串的处理是静默的,不报错但结果未必符合直觉:
-
CAST('' AS SIGNED)→0(空字符串转数字得 0) -
CAST('' AS DATE)→NULL(空字符串转日期得 NULL) -
CAST(NULL AS CHAR)→NULL(保持 NULL,不转成空字符串) - 任何非法输入(如
CAST('xyz' AS SIGNED))都返回 0,而非报错 —— 所以业务上需要前置校验,不能依赖 CAST 报错来拦截脏数据
最常被忽略的一点:CAST 是表达式级别的转换,它不改变原字段定义,也不触发约束检查。如果你需要长期、可索引、可验证的类型表现,应该优先考虑修改表结构(ALTER TABLE ... MODIFY)或加生成列,而不是在每个查询里反复 CAST。











