优先用 concat() 拼接字段,但需用 coalesce() 预处理 null;mysql 中 concat() 自动忽略 null,postgresql/oracle 用 || 时 null 会导致整结果为 null,sql server 用 + 且必须显式转换类型并防 null。

直接拼接多个字段,优先用 CONCAT(),但必须提前处理 NULL 值,否则整条结果变 NULL;不同数据库语法不互通,不能靠记忆混用。
CONCAT() 函数在 MySQL 中最稳妥
CONCAT() 是 MySQL 原生函数,支持任意数量参数,自动跳过 NULL(注意:不是转为空字符串,是“忽略”该参数)。但如果你显式传入 NULL 且希望显示空格或占位符,就得手动包裹 COALESCE()。
- 基础写法:
SELECT CONCAT(name, ' (', id, ')') AS label FROM users; - 含可能为
NULL的字段时:SELECT CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) AS full_name FROM users; - 错误示范:
SELECT CONCAT(first_name, middle_name, last_name)——只要middle_name是NULL,整个结果就是NULL(MySQL 5.7+ 默认行为)
PostgreSQL 和 Oracle 用 || 运算符,但 NULL 更危险
|| 是标准 SQL 字符串连接运算符,在 PostgreSQL、Oracle 中可用,但对 NULL 零容忍:任一操作数为 NULL,结果即 NULL。没有自动忽略机制。
- 安全写法:
SELECT first_name || ' ' || COALESCE(middle_name, '') || ' ' || last_name FROM employees; - 别依赖隐式转换:
age是整型?必须显式转:name || ' (' || CAST(age AS TEXT) || ')',Oracle 则用TO_CHAR(age) - 常见报错:
operator does not exist: text || integer—— 就是忘了类型转换
SQL Server 必须用 +,且所有操作数都得是字符串
SQL Server 不支持 CONCAT()(2012+ 才有,但旧环境仍多见),+ 是唯一原生拼接方式,但它会把 NULL 当作“传播器”,也会拒绝非字符串类型。
- 强制转字符串:
SELECT name + ' - ' + CAST(id AS VARCHAR(10)) FROM users; - 防
NULL推荐写法:ISNULL(first_name, '') + ' ' + ISNULL(last_name, '')(COALESCE也行,但ISNULL性能略优) - 别写
first_name + ' ' + middle_name + ' ' + last_name——中间任意一个NULL,整列全NULL
GROUP_CONCAT / STRING_AGG 是另一类需求,别和字段级拼接混淆
如果目标是把「同一组内的多行某字段值」合并成一行(比如一个用户的所有标签),那不是 CONCAT() 能解决的,得用聚合函数:
- MySQL:
GROUP_CONCAT(tag SEPARATOR ', ') OVER (PARTITION BY user_id)或配合GROUP BY - PostgreSQL:
STRING_AGG(tag, ', ') OVER (PARTITION BY user_id) - 注意:
GROUP_CONCAT默认最大长度 1024,超长静默截断 —— 查SELECT @@group_concat_max_len;,不够就SET SESSION group_concat_max_len = 10000;
跨数据库移植时,最易被忽略的是 NULL 处理逻辑和类型隐式转换限制——看起来只是换了个符号,实际执行时崩得毫无征兆。










