CONCAT()遇NULL必返NULL是SQL标准的null传播行为,非bug;应优先用CONCAT_WS()跳过NULL字段(分隔符不可为NULL),或用COALESCE/IFNULL预处理替换NULL值。

CONCAT() 遇到 NULL 就返回 NULL 是标准行为,不是 bug
只要 CONCAT() 任意一个参数是 NULL,整个结果就是 NULL。这不是 MySQL 的缺陷,而是严格遵循 SQL 标准的 null 传播规则:未知值参与运算,结果仍是未知(NULL)。比如 CONCAT(first_name, ' ', last_name) 中 first_name 为 NULL,哪怕 last_name = 'Li',结果也是 NULL,不是 ' Li'。
WHERE 或 ORDER BY 里用 CONCAT() 拼接字段会丢数据
这种 NULL 传播在过滤和排序时特别危险:
-
WHERE CONCAT(title, content) LIKE '%xxx%':只要title或content任一为NULL,整行就被跳过,查不到本该匹配的记录 -
ORDER BY CONCAT(last_name, ', ', first_name):含NULL的行会被排在最前或最后(取决于NULLS FIRST/LAST设置),且无法预测顺序 - 更隐蔽的是索引失效:
CONCAT()是计算列,数据库没法用title或content上的索引,强制全表扫描
CONCAT_WS() 能跳过 NULL,但分隔符不能为 NULL
CONCAT_WS() 是最省事的替代方案,它自动忽略 NULL 参数,只拼接非 NULL 值:
-
CONCAT_WS(' / ', 'Zhang', NULL, 'Li')→'Zhang / Li' - 但分隔符本身必须是非
NULL值;传入CONCAT_WS(NULL, a, b)会导致整行结果为NULL - 空字符串
''不会被跳过:CONCAT_WS(',', 'a', '', 'c')结果是'a,,c' - 分隔符只能是字面量或列值,不能是表达式(如
CONCAT_WS(COALESCE(suffix, '-'), a, b)会报错)
跨库兼容时,COALESCE() 比 IFNULL() 更稳妥
如果要写可迁移的 SQL(比如将来可能从 MySQL 切到 PostgreSQL 或 SQL Server),优先用 COALESCE():
-
COALESCE(col, '')在所有主流数据库中行为一致,且支持多参数 fallback(如COALESCE(middle_name, nickname, 'N/A')) -
IFNULL(col, '')是 MySQL 特有,PostgreSQL 会报错,SQL Server 要改用ISNULL() - 数值或日期字段必须显式转字符串:
CONCAT(COALESCE(name, ''), ' (', CAST(age AS CHAR), ')'),避免隐式转换出错
真正容易被忽略的点是:你写的拼接逻辑,在 WHERE 或 GROUP BY 里用一次,就等于主动放弃索引和确定性排序;而把 NULL 当成“空”来用,本质上是在用未知值做确定性判断——这两件事都藏在看似简单的函数调用后面。

















