concat遇null返回null是sql标准行为,应优先用concat_ws自动跳过null(首参为非null分隔符),或用ifnull/coalesce显式兜底;where中使用concat会导致索引失效,建议建生成列加索引。

CONCAT() 遇到任意一个参数为 NULL 就返回 NULL,这不是 bug,是 SQL 标准的 null 传播行为。直接用它拼接含空字段的列(比如姓名、地址、备注),结果大概率全变 NULL,应用层容易报空指针。
CONCAT_WS() 自动跳过 NULL,但分隔符不能为 NULL
这是最省事的替代方案,尤其适合拼接地址、人名、标签这类字段不全但结构固定的场景。
-
CONCAT_WS(', ', province, city, district)中任一字段为NULL,不会插空项,也不会多出逗号,结果就是'北京市,朝阳区'这类干净格式 - 第一个参数必须是非
NULL的分隔符;传CONCAT_WS(NULL, a, b)整行结果直接变NULL - 空字符串
''不会被跳过:CONCAT_WS(',', 'a', '', 'c')→'a,,c' - 分隔符只能是字面量或列值,不能是表达式,比如
CONCAT_WS(COALESCE(suffix, '-'), a, b)会报错
IFNULL() 和 COALESCE() 显式兜底,适合模板化拼接
当你需要每个位置都“占位”(哪怕填空字符串),或者要加括号、前缀、转类型时,显式替换更可控。
-
IFNULL(col, '')是 MySQL 特有,性能略好,但只支持两个参数 -
COALESCE(col, '')兼容性更好,还能 fallback 多级:COALESCE(middle_name, nickname, 'N/A') - 数值或日期字段必须显式转字符串:
CONCAT(COALESCE(name, ''), ' (', CAST(age AS CHAR), ')'),避免隐式转换出错或截断
WHERE 条件里用 CONCAT 就等于放弃索引
写 WHERE CONCAT(first_name, last_name) LIKE '%john%' 看似方便,实际会让 first_name 和 last_name 上的索引完全失效,强制全表扫描。
- 高频模糊搜索别硬扛,建生成列+索引才是正解:
ALTER TABLE users ADD full_name VARCHAR(200) GENERATED ALWAYS AS (CONCAT_WS(' ', first_name, last_name)) STORED,再对full_name加索引 - 字符集不一致也会触发隐式转换,导致索引失效或报
Illegal mix of collations错误,拼接前先确认字段字符集是否统一
CONCAT_WS() 快,但没控制力;用 COALESCE() 稳,但写起来啰嗦;而一旦进 WHERE,就得提前想好索引怎么建。











