优先用CONCAT_WS而非CONCAT,因其自动跳过NULL字段值而不返回NULL;但分隔符为NULL时整体结果为NULL,空字符串仍参与拼接,且不支持索引。

MySQL 里拼接多个字段,优先用 CONCAT_WS,而不是 CONCAT;除非你明确需要 NULL 控制逻辑,否则 CONCAT 容易让整行结果变 NULL。
MySQL 中 CONCAT 遇到 NULL 就全崩了
它不是跳过 NULL,是“只要有一个参数为 NULL,结果就一定是 NULL”。比如用户表里 middle_name 允许为空:
SELECT CONCAT(first_name, ' ', middle_name, ' ', last_name) FROM users;
哪怕只有 middle_name 是 NULL,整条记录返回的就是 NULL,不是 'Zhang Li',连空格都看不到。
- 必须手动兜底:用
COALESCE(middle_name, '')或IFNULL(middle_name, '')替换所有可能为空的字段 - 数字、日期字段会被隐式转字符串,但
CONCAT(123, NOW())这种写法在低版本 MySQL 可能报错,建议显式转:CONCAT(123, CAST(NOW() AS CHAR)) -
CONCAT不走索引——如果 WHERE 条件里写WHERE CONCAT(name, id) = 'Alice1001',基本等于全表扫描
用 CONCAT_WS 更省心,尤其要加固定分隔符时
CONCAT_WS 的第一个参数是分隔符(separator),后面才是字段。它的关键优势是:分隔符本身不能为 NULL(否则整条返回 NULL),但字段值为 NULL 会被自动跳过,不插空档、不漏分隔符。
SELECT CONCAT_WS(' / ', first_name, middle_name, last_name) FROM users;
当 middle_name 是 NULL,结果就是 'Zhang / Li',不是 'Zhang / / Li'。
- 分隔符写错成
CONCAT_WS(NULL, ...)会直接让整列变NULL,务必检查第一个参数 - 想用空格分隔?写
CONCAT_WS(' ', a, b, c),别写成CONCAT(a, ' ', b, ' ', c)—— 后者一空全空 - 分隔符支持多字符,比如
CONCAT_WS(' → ', dept, team, role),比嵌套CONCAT清晰得多
跨行聚合拼接必须用 GROUP_CONCAT,不是 CONCAT 的事
CONCAT 和 CONCAT_WS 都是逐行计算的标量函数。如果你要“把一个用户的所有标签合并成逗号串”,那是聚合场景,得靠 GROUP_CONCAT:
SELECT user_id, GROUP_CONCAT(tag SEPARATOR ', ') FROM user_tags GROUP BY user_id;
它天然支持去重(DISTINCT)、排序(ORDER BY)、长度截断(GROUP_CONCAT(... SEPARATOR ',' LIMIT 10) 不行,得靠 GROUP_CONCAT 的 MAX_LENGTH 系统变量或子查询)。
- 默认最大长度是 1024 字符,超长会被无声截断,查不到完整结果——先确认
SELECT @@group_concat_max_len; - 不能在
ON或WHERE子句里直接用GROUP_CONCAT做关联条件,它是聚合后结果,不是原始字段 - 如果要拼接后还参与排序或筛选,别硬扛在 SQL 层,应用层处理更可控
真正容易被忽略的点是:数据库类型决定函数行为。MySQL 的 CONCAT 和 SQL Server 的 CONCAT 表面一样,内核逻辑相反——前者见 NULL 就停,后者自动转空串。跨库迁移或写通用 DAO 时,这点不核对清楚,上线后数据就“消失”了。










