CONCAT函数遇NULL即返NULL,需用CONCAT_WS、IFNULL或COALESCE规避;拼接时注意隐式类型转换、字符集兼容性;WHERE中使用会导致索引失效,建议用生成列加索引优化。

CONCAT 函数能拼接多个字段,但遇到 NULL 会直接让整条结果变 NULL——这是最常踩的坑。
CONCAT 的基本用法和 NULL 陷阱
MySQL 的 CONCAT 是逐参数拼接,不自动跳过 NULL。只要任一参数是 NULL,整个返回值就是 NULL。
比如:SELECT CONCAT(first_name, ' ', last_name) FROM users;,如果 first_name 为 NULL,结果就是 NULL,不是 ' NULL' 或空字符串。
- 用
CONCAT_WS(带分隔符)更安全:它会跳过NULL参数,只拼接非空值 - 显式处理
NULL:用IFNULL(col, '')或COALESCE(col, '')替换 -
CONCAT不接受可变参数列表,必须明确写出每个字段或表达式
CONCAT_WS 比 CONCAT 更适合多字段拼接
当你要用固定分隔符(如空格、逗号)连接多个字段时,CONCAT_WS 是更鲁棒的选择。
示例:SELECT CONCAT_WS(' ', first_name, middle_name, last_name) FROM users;
- 第一个参数是分隔符,后面所有参数都会被检查;
NULL值会被忽略,不会中断拼接 - 如果
middle_name是NULL,结果等价于CONCAT(first_name, ' ', last_name) - 注意:
CONCAT_WS的分隔符本身不能是NULL,否则整条结果为NULL
字段类型不一致时的隐式转换风险
CONCAT 会把非字符串类型(如数字、日期)转成字符串再拼接,但转换规则可能不符合预期。
例如:SELECT CONCAT(id, ' - ', created_at) FROM posts; 中,created_at 是 DATETIME,会被转成类似 '2024-05-12 14:23:08' 的格式,但如果列是 TIMESTAMP 且含时区,实际值可能因会话时区不同而变化。
- 数值类字段建议显式用
CAST(col AS CHAR)或CONVERT(col, CHAR)控制精度 - 日期类字段优先用
DATE_FORMAT(col, '%Y-%m-%d')明确格式,避免依赖默认转换 - 拼接前用
CHARSET()和COLLATION()检查各字段字符集,混合utf8mb4和latin1可能触发隐式降级或报错
性能与索引失效提醒
在 WHERE 或 ORDER BY 中对拼接结果做操作,几乎必然导致索引失效。
例如:WHERE CONCAT(last_name, ', ', first_name) = 'Smith, John' 无法使用 last_name 或 first_name 上的索引。
- 如需高频按拼接结果查询,考虑加生成列(Generated Column)并建索引:
ALTER TABLE users ADD full_name VARCHAR(255) GENERATED ALWAYS AS (CONCAT_WS(' ', last_name, first_name)) STORED, ADD INDEX idx_full_name (full_name); -
CONCAT本身开销极小,但若嵌套多层函数(如CONCAT(UPPER(...), LOWER(...))),每行都会触发多次计算,大数据量下可观测到 CPU 上升 - 避免在大文本字段(如
TEXT)上直接CONCAT,尤其配合LIKE使用,容易触发全表扫描
真正麻烦的从来不是怎么写 CONCAT,而是没意识到 NULL 会吃掉整条结果,或者在 WHERE 里随手一拼就让索引躺平了。


















