优先用CAST(expr AS type),因CAST支持长度声明(如CHAR(20))且跨库兼容;CONVERT仅在字符集转换(CONVERT(expr USING charset))时不可替代,其余类型转换场景中不支持长度、不兼容VARCHAR/INTEGER等写法,易报错。

优先用 CAST(expr AS type),除非你要转字符集——那是 CONVERT(expr USING charset) 的专属场景。 其他情况硬套 CONVERT(expr, type) 不但没优势,还容易因语法细节翻车。
CAST 和 CONVERT 在 MySQL 里到底能不能互换?
能,但只在“类型转换”这一条路上勉强同行;一旦涉及长度声明或字符集,立刻分道扬镳。
-
CAST('123' AS CHAR(20))合法,CONVERT('123', CHAR(20))直接报错 ——CONVERT()不支持带括号的类型长度声明 -
CONVERT('hello' USING utf8mb4)合法,CAST('hello' AS utf8mb4)语法错误 ——CAST()完全不处理字符集 - 目标类型名大小写不敏感,但别写
VARCHAR:CONVERT()和CAST()都只认CHAR,写VARCHAR(10)会失败 - 数值类型别写
INTEGER:CAST('123' AS INTEGER)在 MySQL 中不识别,得用SIGNED或UNSIGNED
字符串转数字时,MySQL 从不报错,只悄悄给你 0
这是线上逻辑错乱的头号温床。你查不到报错,但 WHERE amount > 100 却漏掉所有非法值行,因为它们全被转成了 0。
-
CAST('abc' AS SIGNED)→ 返回0(不是NULL,也不是报错) -
CAST(' 42kg' AS SIGNED)→ 返回42(前导空格忽略,遇到非数字就停) -
CAST('kg42' AS SIGNED)→ 返回0(开头不是数字,直接归零) - 真要过滤,得前置校验:
WHERE col REGEXP '^[0-9]+$',或包一层IF:CAST(IF(col REGEXP '^[0-9]+$', col, NULL) AS SIGNED)
WHERE 或 ORDER BY 里用 CAST/CONVERT = 主动放弃索引
哪怕 phone_num 是 BIGINT 并建了索引,只要写成 WHERE CAST(phone_num AS CHAR) LIKE '138%',MySQL 就只能全表扫。
- 根本解法不是优化函数,而是修正数据模型:该是字符串的字段,就别存成数字
- 如果必须兼容两种查询方式(比如既要按数字比较又要按前缀匹配),考虑用生成列:
ALTER TABLE users ADD phone_str VARCHAR(20) STORED AS (CAST(phone_num AS CHAR)),再给phone_str加索引 - 日期字符串转换尤其危险:
CAST(log_time AS DATE) = '2026-09-29'看似合理,但如果原始数据含'2026/09/29'或'29-09-2026',结果不可控且无法索引
最常被忽略的一点:类型转换不是兜底工具,而是最后一道防线。它解决不了设计缺陷,也掩盖不了脏数据。真正安全的转换,永远发生在清洗之后、入库之前,而不是在查询时临时抱佛脚。


















