CONCAT函数在MySQL中遇NULL返回NULL,PostgreSQL推荐concat()函数(跳过NULL),SQL Server的CONCAT自动将NULL转为空字符串;拼接时需注意分隔符、空值处理及性能影响。

CONCAT函数在不同数据库中的行为差异
MySQL 5.0.15+ 的 CONCAT 会把任意参数转为字符串,遇到 NULL 就让整个结果变 NULL;PostgreSQL 没原生 CONCAT,得用 || 或 concat()(后者对 NULL 更友好);SQL Server 2012+ 才支持 CONCAT,且自动把 NULL 转成空字符串——这点和 MySQL 完全相反。
实际写法必须先确认数据库类型,否则查出来一堆 NULL 还以为数据丢了。
- MySQL:直接用
CONCAT(col1, col2),但记得套IFNULL或COALESCE处理空值 - PostgreSQL:优先用
concat(col1, col2)(它跳过NULL),别用||,因为'a' || NULL结果是NULL - SQL Server:放心用
CONCAT(col1, col2),NULL自动变空串,但注意它不接受非字符串类型,数字得显式转:CONCAT(name, CAST(age AS VARCHAR))
拼接时加空格或分隔符的常见写法
直接连写 CONCAT(first_name, last_name) 会变成 “ZhangSan”,中间没空格。加固定字符最稳妥的方式是把分隔符也当参数传进去。
例如要输出 “Zhang San”:
SELECT CONCAT(first_name, ' ', last_name) FROM users;
但要注意:如果 first_name 是 NULL,MySQL 下整条结果就没了。更安全的是:
SELECT CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) FROM users;
- 别用
+拼接(SQL Server 旧写法),容易因隐式转换报错,比如字符串 + 数字 - 分隔符不要硬写在字段里(如
last_name + ' '),逻辑分散难维护 - 需要动态分隔符(比如有的记录用逗号、有的用顿号)就别用
CONCAT,改用CASE WHEN配合
CONCAT性能问题:不是所有场景都适合用
CONCAT 是逐行计算的标量函数,数据量大时会影响查询速度,尤其是配合 WHERE 或 ORDER BY 使用时,数据库很难走索引。
- 如果只是展示用,且字段本身有索引,尽量把拼接逻辑移到应用层(比如 Python 或 Java 里做)
- 如果必须在 SQL 层拼,又常按拼接结果筛选,考虑建计算列(MySQL 5.7+ 支持
GENERATED COLUMN)并加索引 - 避免在
ON条件里用CONCAT关联表,比如ON CONCAT(a.x, a.y) = b.z,基本等于放弃索引
替代方案:什么时候该换别的方法
当拼接逻辑变复杂——比如要过滤空字段、去重、排序后再连起来——CONCAT 就力不从心了。
例如合并一个用户所有标签,用逗号分隔:
-- MySQL 8.0+ SELECT user_id, GROUP_CONCAT(tag ORDER BY tag SEPARATOR ', ') FROM user_tags GROUP BY user_id;
再比如 PostgreSQL 中处理多字段可选拼接:
-- 只拼非空字段,且自动跳过 NULL
SELECT concat_ws(' / ', name, department, title) FROM staff;
-
GROUP_CONCAT(MySQL)、STRING_AGG(PostgreSQL)、STRING_AGG(SQL Server)更适合集合类拼接 -
CONCAT_WS(with separator)比手写多个CONCAT更简洁,且天然忽略NULL - 嵌套太多
CONCAT(COALESCE(...), ...)时,代码可读性急剧下降,不如拆成子查询或 CTE
真正麻烦的不是语法怎么写,而是想清楚“这个拼接结果后续要不要参与计算、筛选或排序”。一旦涉及这些,就得重新评估放在 SQL 层是否合理。










