mysql中concat遇null即返回null,必须用coalesce或ifnull兜底;concat_ws可跳过null字段但分隔符不能为null;跨库语法差异大,where中使用会失效索引。

CONCAT 本身不安全,直接用必踩 NULL 坑——MySQL 中任一参数为 NULL,结果就是 NULL,不是空字符串,也不是跳过。
MySQL 里 CONCAT 遇到 NULL 就全崩,必须提前兜底
你写 CONCAT(first_name, ' ', last_name),只要 first_name 或 last_name 是 NULL,整行结果就是 NULL,前端看到的是一片空白,而不是“张 三”或“张”。这不是 bug,是 MySQL 的明确行为。
- 别指望
CONCAT_WS('', col1, col2)能绕开——它照样崩,因为分隔符为NULL时整个结果也是NULL - 每个可能为
NULL的字段都得单独包一层COALESCE(col, '')或IFNULL(col, ''),不能只在外层包一次 - 如果中间名允许为空,又想保持“张 三”这种单空格格式,得额外套
TRIM(),CONCAT_WS(' ', ...)不会帮你去多余空格
优先用 CONCAT_WS 而不是 CONCAT,但注意分隔符不能为 NULL
CONCAT_WS 是 MySQL 里拼接多字段的默认安全选择:它自动跳过值为 NULL 的字段,且不插空档。比如 CONCAT_WS(' / ', first_name, middle_name, last_name),当中间名为 NULL,结果就是 '张 / 三',不是 '张 / / 三'。
- 第一个参数是分隔符,它本身不能为
NULL;写成CONCAT_WS(NULL, a, b)会整列变NULL - 空字符串
''是合法分隔符,CONCAT_WS('', a, b)等价于CONCAT(a, b),但依然跳过NULL - 它不支持在分隔符位置用表达式,比如
CONCAT_WS(IFNULL(suffix, '-'), ...)会报错
跨数据库写法差异大,别抄错语法
PostgreSQL 和 SQL Server 的 CONCAT 行为跟 MySQL 完全不同:它们把 NULL 当作 '' 处理,但对类型更敏感。
- SQL Server:
CONCAT('Name: ', name, ', Age: ', age)能跑,内部自动转类型 - PostgreSQL:
age是INTEGER就必须显式转,写成age::TEXT或CAST(age AS TEXT),否则报错ERROR: concatenation requires all arguments to be of the same type - SQLite 根本没有
CONCAT,得用||运算符,且NULL || 'a'结果仍是NULL,必须先COALESCE(col, '')
WHERE 里用 CONCAT 就等于放弃索引
写 WHERE CONCAT(title, content) LIKE '%关键词%',数据库没法走 title 或 content 上的索引,必然全表扫描。
- 真要按拼接内容检索,优先建生成列:
ALTER TABLE articles ADD full_text TEXT GENERATED ALWAYS AS (CONCAT_WS(' ', title, content)) STORED,再给full_text加索引 - 或者改用多字段 OR:
WHERE title LIKE ? OR content LIKE ?,语义准、能走索引 - 应用层拼接也比在 WHERE 里硬套
CONCAT更可控、更易调试
最常被忽略的点是:你以为在 SQL 里拼接只是“连几个字段”,实际上它牵扯 NULL 处理逻辑、类型隐式转换、索引可用性、跨库兼容性四层问题。一个 CONCAT 写错,轻则数据展示异常,重则整批查询变慢甚至失败。











