concat函数遇null即返回null,是sql标准的null传播性行为;需用ifnull/coalesce转空字符串或改用concat_ws自动跳过null。

CONCAT 函数拼接时遇到 NULL 就整个变 NULL
直接用 CONCAT(col1, col2, col3) 拼接,只要其中任意一列是 NULL,结果就变成 NULL —— 这不是漏数据,是 SQL 标准行为。比如 CONCAT('张', NULL, '三') 返回 NULL,而不是 '张三'。
解决办法是提前把 NULL 转成空字符串:CONCAT(IFNULL(col1, ''), IFNULL(col2, ''), IFNULL(col3, ''))。MySQL 8.0+ 可用 COALESCE(col1, '') 替代 IFNULL,兼容性稍好。
- 别依赖隐式转换:
CONCAT(col1 + '', col2)在数值列上看似可行,但遇到字符串含非数字字符会报错或截断 - 字段类型混用时(如
INT和VARCHAR),CONCAT会自动转字符串,但建议显式用CAST(col AS CHAR)控制精度
CONCAT_WS 更适合带分隔符的多列合并
CONCAT_WS 的第一个参数是分隔符(W 表示 With Separator),后续参数自动跳过 NULL 值,不用手动 IFNULL。例如:CONCAT_WS('-', col1, col2, col3) 中若 col2 是 NULL,结果形如 '北京-朝阳',不会出现 '北京--朝阳'。
但它不跳过空字符串('')——CONCAT_WS(',', 'a', '', 'c') 结果是 'a,,c'。如果业务要求过滤空值,得先用 CASE WHEN col != '' THEN col END 或子查询预处理。
- 分隔符可以是任意字符串,包括空格、制表符甚至 emoji,但注意长度限制(MySQL 中最大 255 字节)
- 不能把分隔符写成变量再传入(如
CONCAT_WS(@sep, ...))——语法错误,必须是字面量或列值表达式
不同数据库对 CONCAT 的兼容性差异很大
MySQL 的 CONCAT 支持任意数量参数,但 PostgreSQL 没有 CONCAT 函数,得用 || 操作符(如 col1 || col2 || col3),且 NULL || 'x' 仍为 NULL;SQL Server 用 +,同样受 NULL 传染。
跨库可移植写法推荐 CONCAT_WS('', ...)(空分隔符)配合 COALESCE:它在 MySQL、PostgreSQL(需 v9.1+)、SQL Server(v2017+)都存在,语义一致。
- SQLite 只有
||,没有CONCAT或CONCAT_WS - Oracle 用
CONCAT()但只接受两个参数,三个以上得嵌套:CONCAT(CONCAT(a,b),c)
性能敏感场景下避免在 WHERE 或 JOIN 条件里用 CONCAT
在 WHERE CONCAT(first_name, last_name) = 'ZhangSan' 这类条件中,数据库无法使用 first_name 或 last_name 上的索引,会强制全表扫描。即使加了函数索引(MySQL 8.0+),维护成本也高。
真实业务中,更稳妥的是拆开判断:WHERE first_name = 'Zhang' AND last_name = 'San',或在应用层拼接后查,而不是让数据库每次执行都计算。
- 如果必须模糊匹配拼接结果(如查“张*三”),考虑生成持久化计算列并建索引:
ALTER TABLE t ADD full_name VARCHAR(100) STORED AS (CONCAT(first_name, last_name)) -
CONCAT_WS在 GROUP BY 或 ORDER BY 中使用时,同样会抑制索引使用,需结合执行计划EXPLAIN验证










