MySQL的CONCAT函数在5.0.12+版本中默认将NULL视为空字符串处理,返回非NULL结果;但CONCAT_WS要求分隔符非NULL,否则报错;需根据业务是否保留NULL语义选择CONCAT、CONCAT_WS或COALESCE。

CONCAT函数本身就能安全处理NULL值
MySQL 5.0.12+ 的 CONCAT 函数默认把 NULL 当作空字符串处理,不会让整个结果变 NULL。这点和传统 + 或 || 拼接完全不同——后者遇到任意一个 NULL 就返回 NULL。
比如:CONCAT('a', NULL, 'b') 返回 'ab',不是 NULL。这是它最实用的特性,无需额外判断。
但要注意CONCAT_WS和COALESCE的适用边界
CONCAT_WS(带分隔符拼接)也跳过 NULL 参数,但它要求第一个参数是分隔符,且该分隔符不能为 NULL,否则整条语句报错:ERROR 1582 (42000): Incorrect parameter count in the call to native function 'CONCAT_WS'。
- ✅ 正确:
CONCAT_WS('-', 'a', NULL, 'c')→'a-c' - ❌ 错误:
CONCAT_WS(NULL, 'a', 'b')→ 直接报错 - ⚠️ 注意:
CONCAT_WS('', 'a', NULL)是合法的,结果为'a',但空分隔符容易引发逻辑误解
当需要保留NULL语义时,不能依赖CONCAT自动转换
如果业务上明确要求“只要任一字段为NULL,结果就应为NULL”(比如构造唯一标识符,缺一不可),那 CONCAT 就不合适了。此时得手动干预:
- 用
COALESCE显式转空字符串:CONCAT(COALESCE(col1, ''), COALESCE(col2, '')) - 或用条件判断强制NULL传播:
CASE WHEN col1 IS NULL OR col2 IS NULL THEN NULL ELSE CONCAT(col1, col2) END - 注意:MySQL 8.0+ 支持
CONCAT的严格模式(sql_mode含STRICT_TRANS_TABLES),但不影响NULL处理逻辑,只影响截断警告
跨数据库兼容性差,别写死在应用逻辑里
PostgreSQL、SQL Server、Oracle 的 CONCAT 行为不一致:PostgreSQL 的 CONCAT 确实也忽略 NULL,但 SQL Server 的 CONCAT 是 2012+ 才加的,且行为类似;而 Oracle 12c 之前压根没有 CONCAT(只有双管道 ||,遇 NULL 即停)。如果SQL要复用或迁移:
- 优先考虑
COALESCE(col, '')显式转换,兼容性最好 - 避免依赖 MySQL 特有的
CONCAT隐式行为做关键业务拼接 - 尤其注意视图或存储过程里用了
CONCAT,换库时很可能静默出错
真正容易被忽略的是:开发时在MySQL里测试通过的拼接逻辑,上线到混合数据库环境或ORM自动生成SQL时,可能因底层方言切换而崩掉——不是语法错,是语义错。

















