用 cast(expr as type) 更稳妥,convert(expr, type) 功能等价但不支持长度参数;二者无性能差异,但类型名错误或非法值时行为不同,且 cast 语义更清晰、兼容性更好。

直接结论:用 CAST(expr AS type) 更稳妥,CONVERT(expr, type) 功能等价但语法不支持长度参数;二者在类型转换上无性能差异,但写错类型名或传入非法值时行为不同。
CAST 和 CONVERT 的语法差异必须分清
很多人以为两个函数只是括号写法不同,其实关键区别在细节:
-
CAST('123' AS CHAR(10))合法,能指定字符串长度;CONVERT('123', CHAR(10))会报错 ——CONVERT()不接受带括号的类型声明 -
CONVERT('hello' USING utf8mb4)合法,用于字符集转码;CAST('hello' AS utf8mb4)直接报错 ——CAST()完全不支持USING语法 - 目标类型名大小写不敏感,
SIGNED、signed、INTEGER(注意:MySQL 实际不认INTEGER,得用SIGNED或UNSIGNED)
数值转字符串该用哪个?优先选 CAST
显式转字符串最常见,比如把 price(INT)拼进日志或展示字段。这里 CAST() 语义更清晰、兼容性更好:
-
CAST(price AS CHAR):默认按需分配长度,安全可靠 -
CAST(price AS CHAR(20)):强制固定长度,适合对齐或导出场景 -
CONVERT(price, CHAR):能用,但无法指定长度;若后续迁移到 PostgreSQL 或 SQL Server,CONVERT()会不识别 - 避免隐式拼接如
price + '':它依赖 MySQL 的宽松模式,且空值参与时结果不可控(NULL + ''得NULL,而CAST(NULL AS CHAR)明确也是NULL)
字符串转数字时,失败不是报错而是静默归零
这是最容易踩坑的地方:MySQL 默认不会中断查询,而是返回 0 或空字符串,导致逻辑错误难定位。
-
CAST('abc123' AS SIGNED)→ 返回0(不是报错) -
CAST(' 123xyz' AS SIGNED)→ 返回123(前导空格忽略,后续非数字截断) -
CAST('' AS SIGNED)→ 返回0;CAST(NULL AS SIGNED)→ 返回NULL - 真要校验,得前置判断:
WHERE col REGEXP '^[0-9]+$'或用IF包裹:CAST(IF(col REGEXP '^[0-9]+$', col, NULL) AS SIGNED)
WHERE 或 ORDER BY 中用 CAST 基本等于放弃索引
哪怕字段本身有索引,只要在条件或排序里对它用了 CAST 或 CONVERT,MySQL 就没法走索引扫描,只能全表扫描。
- 反例:
WHERE CAST(phone_num AS CHAR) LIKE '138%'—— 即使phone_num是BIGINT且建了索引,也失效 - 正解:如果字段本应是字符串,就别存成数字;如果必须混合查询,考虑生成列(generated column)加索引:
ALTER TABLE users ADD phone_str VARCHAR(20) STORED AS (CAST(phone_num AS CHAR)),再对phone_str建索引 -
ORDER BY CAST(created_at AS DATE)同样触发文件排序(Using filesort),不如在应用层或视图里处理
真正麻烦的不是语法怎么写,而是转换后数据是否还“可信”——尤其当原始字段混杂脏数据、空格、单位、非标准日期格式时,CAST 和 CONVERT 都不会主动提醒你。先清洗,再转换,比靠函数兜底靠谱得多。











