mysql 5.7+的concat忽略null,低版本则返回null;跨版本应使用coalesce兜底或concat_ws自动跳过null,where中避免对concat结果判空以防索引失效。

CONCAT函数本身不传播NULL,但MySQL版本差异极大
MySQL 5.7+ 的 CONCAT 函数天然忽略 NULL 参数,不会让整行变空;但低版本(如5.6及更早)或某些兼容模式下,只要任一参数为 NULL,结果就是 NULL。这不是 bug,是历史行为差异——关键看你的 MySQL 实际版本和 SQL mode。
实操建议:
- 先运行
SELECT VERSION();确认版本;若低于 5.7,别依赖CONCAT自动跳过NULL - 检查当前 mode:
SELECT @@sql_mode;,若含STRICT_TRANS_TABLES或ERROR_FOR_DIVISION_BY_ZERO等,可能影响隐式转换行为 - 跨版本可移植写法:统一用
CONCAT(COALESCE(col1, ''), COALESCE(col2, ''))
用COALESCE把NULL转为空字符串最稳妥
COALESCE 是标准 SQL 函数,返回第一个非 NULL 值,在拼接前兜底处理字段,彻底切断 NULL 向 CONCAT 透传的路径。比 IFNULL 更通用(后者是 MySQL 特有),也比 IF 表达式简洁。
常见错误现象:直接写 CONCAT(first_name, ' ', last_name),当 last_name 为 NULL 时,整结果变 NULL(尤其在视图或 GROUP BY 场景中,会“消失”)。
正确写法示例:
SELECT CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) AS full_name FROM users;
注意点:
-
COALESCE第二个参数必须是字符串(如''),不能是数字或NULL,否则类型转换可能出错 - 如果字段是数值型(如
age),需显式转字符串:COALESCE(CAST(age AS CHAR), '') - 多个字段拼接时,每个都套一层
COALESCE,别只包最后一个
替代方案:用CONCAT_WS避免手写分隔符和NULL判断
CONCAT_WS(W = With Separator)是 MySQL 内置函数,第一个参数是分隔符,后续参数自动跳过 NULL —— 它的行为在所有支持版本中一致,且不传播 NULL。适合拼接带固定分隔符的字段,比如地址、姓名、标签列表。
使用场景:拼接 province、city、district,其中任意字段可能为空,但不想出现连续顿号或空格。
示例:
SELECT CONCAT_WS(' - ', province, city, district) AS address FROM locations;
优势与限制:
- 分隔符只出现在非
NULL参数之间,不会开头或结尾多出分隔符 - 不能控制不同字段用不同分隔符(比如姓和名之间用空格,名和后缀之间用逗号)
- 如果所有参数都是
NULL,结果是空字符串'',不是NULL—— 这通常正是你想要的
WHERE子句里别用CONCAT结果判NULL,性能会崩
有人想“保险起见”,在查询条件里写 WHERE CONCAT(COALESCE(a,''), COALESCE(b,'')) IS NOT NULL,这会导致全表扫描:数据库无法对函数结果走索引。哪怕字段本身有索引,CONCAT 一包就废。
真正要过滤掉整行为空的情况,应拆解判断:
- 明确业务语义:是“所有字段都为空/NULL”才排除?还是“任一关键字段为NULL”就排除?
- 对应写成:
WHERE a IS NOT NULL OR b IS NOT NULL(或用AND) - 如果字段定义允许空字符串,还需加上
a != ''等判断,NULL和''在 SQL 中不等价
函数包裹后的字段几乎无法优化,这个坑比拼接逻辑本身更隐蔽。










