concat遇null返回null,应改用concat_ws自动跳过null或用ifnull/coalesce转换;注意字符集一致、索引失效及条件拼接宜用case或json_object。

MySQL 用 CONCAT 拼接字段时 NULL 会让整条结果变 NULL
这是最常踩的坑:只要 CONCAT 里任意一个参数是 NULL,整个返回值就是 NULL,不是空字符串。比如 CONCAT(first_name, ' ', last_name),如果 last_name 是 NULL,那整段就没了。
解决办法是提前把 NULL 转成空字符串:
- 用
IFNULL(col, '')或COALESCE(col, '')包一层 - 更省事的是直接用
CONCAT_WS(' ', col1, col2, col3)—— 它自动跳过NULL值,只用指定分隔符连接非空项 - 注意
CONCAT_WS第一个参数必须是分隔符(如' '),后面才是要拼的字段
CONCAT 和 CONCAT_WS 在实际查询中的写法差异
两者都用于拼接,但行为和适用场景不同:
-
CONCAT('Hello', ' ', 'World')→'Hello World';任一参数为NULL则结果为NULL -
CONCAT_WS('-', 'a', NULL, 'c')→'a-c';NULL被忽略,不会插入额外分隔符 - 想拼地址字段(省、市、区)且允许某些字段为空,优先选
CONCAT_WS(', ', province, city, district) - 需要严格控制每个位置是否出现内容(比如固定格式模板),才用
CONCAT配合IFNULL
性能和字符集问题:拼接后字段类型可能影响索引或比较
CONCAT 返回的是字符串,但具体类型取决于输入字段的字符集和排序规则。如果拼接字段来自不同表、不同字符集(比如 utf8mb4 和 latin1),MySQL 会隐式转换,可能触发全表扫描或报错 Illegal mix of collations。
- 查表时加
SHOW CREATE TABLE table_name确认各字段字符集是否一致 - 必要时显式转码:
CONCAT(CONVERT(col1 USING utf8mb4), ' ', CONVERT(col2 USING utf8mb4)) - 拼接结果无法走索引 —— 别指望
WHERE CONCAT(name, '_tmp') = 'xxx_tmp'能用上name的索引
替代方案:用 CASE 或 JSON_OBJECT 处理复杂拼接逻辑
纯 CONCAT 不适合带条件的拼接,比如“有手机号才显示,没电话就不加‘Tel:’前缀”。这时候硬套 CONCAT 会写得很绕。
- 用
CASE WHEN phone IS NOT NULL THEN CONCAT('Tel:', phone) ELSE '' END - 如果目标是生成结构化文本(如日志、导出字段),
JSON_OBJECT('name', name, 'age', age)更清晰,也避免引号/转义问题 - 注意
JSON_OBJECT要求 MySQL ≥ 5.7,且所有键名必须是字符串字面量
真正麻烦的从来不是怎么拼,而是拼完要不要参与 WHERE、ORDER BY 或导出到外部系统——这些地方字符集、NULL 处理、长度截断最容易悄悄出错。











