MySQL中CONCAT()遇NULL即返回NULL,并非跳过;应使用CONCAT_WS()自动忽略NULL,或用COALESCE/IFNULL预处理,避免结果全为NULL。

MySQL 中用 CONCAT() 合并字符串列
MySQL 不支持标准 SQL 的 || 连接操作符(除非开启 PIPES_AS_CONCAT 模式),必须用 CONCAT() 函数。它会自动跳过 NULL 值——这点容易误判:如果任一参数为 NULL,整个结果就是 NULL,不是跳过该字段。
常见错误现象:SELECT CONCAT(first_name, ' ', last_name) 返回 NULL,只因为 last_name 是 NULL。
- 用
CONCAT_WS(' ', first_name, middle_name, last_name)更安全:第一个参数是分隔符,自动忽略NULL参数 - 若需保留空格占位(如“张 NULL 三”要变成“张 三”),改用
CONCAT(IFNULL(first_name, ''), ' ', IFNULL(last_name, '')) - 注意字符集:若列使用不同 collation(如
utf8mb4_unicode_ci和utf8mb4_general_ci),CONCAT()可能报错Illegal mix of collations,需显式转换:CONCAT(CAST(col1 AS CHAR CHARACTER SET utf8mb4), col2)
PostgreSQL 中用 || 或 CONCAT() 都行,但行为不同
PostgreSQL 原生支持 || 操作符,且对 NULL 更宽容:只要左右任一操作数非 NULL,结果就非 NULL(NULL || 'abc' 得 'abc');而 CONCAT() 函数才真正跳过 NULL。
- 推荐日常用
||:简洁、符合直觉,SELECT first_name || ' ' || last_name FROM users - 若某列可能全
NULL且你希望结果为空字符串而非NULL,加COALESCE:COALESCE(first_name, '') || ' ' || COALESCE(last_name, '') -
CONCAT()在 PostgreSQL 中是变参函数,不强制要求非空,适合动态拼接不确定数量的字段
SQL Server 的 + 运算符默认会把 NULL 转成空字符串?不,会传染
SQL Server 的字符串拼接用 +,但它有个反直觉规则:任意操作数为 NULL,结果必为 NULL(不像 PostgreSQL)。很多人误以为它像 Python 的 + 会隐式转空字符串。
- 必须手动处理
NULL:ISNULL(first_name, '') + ' ' + ISNULL(last_name, '')(ISNULL比COALESCE稍快,且只接受两个参数) - 如果列是
varchar(max),直接+可能触发隐式转换失败,建议统一显式转:CAST(ISNULL(first_name, '') AS VARCHAR(100)) + ' ' + CAST(ISNULL(last_name, '') AS VARCHAR(100)) - 避免在 WHERE 或 JOIN 条件中拼接后比较——索引失效,性能骤降
跨数据库可移植写法:用标准 CONCAT() + COALESCE
ANSI SQL-2008 定义了 CONCAT(),但各厂商实现有差异:MySQL 要求至少两个参数,PostgreSQL 允许零参,SQL Server 2012+ 才支持。真正能跨库跑通的底线是:用 CONCAT() 包裹每个字段的 COALESCE。
例如合并三列,兼容 MySQL 5.7+、PostgreSQL 9.1+、SQL Server 2012+:
SELECT CONCAT(
COALESCE(first_name, ''),
COALESCE(' ', ''),
COALESCE(middle_name, ''),
COALESCE(' ', ''),
COALESCE(last_name, '')
) AS full_name
FROM users;
实际项目里别硬套这个——性能差、可读性低。优先按目标数据库选原生语法,只在需要写一次跑多库的工具脚本时才考虑它。真正的坑不在函数名,而在 NULL 处理逻辑和字符集隐式转换,这两点漏掉一个,查询就静默出错或返回空。

















