STRING_AGG是PostgreSQL 9.0+和SQL Server 2017+原生聚合函数,用于多行字符串拼接;核心语法为STRING_AGG(expression, separator),expression为待拼接列或表达式,separator为必填非NULL分隔符,需配合GROUP BY使用,排序须用WITHIN GROUP (ORDER BY ...)显式声明,NULL值默认跳过。

STRING_AGG 用法和基本语法结构
直接说结论:STRING_AGG 是 PostgreSQL 9.0+ 和 SQL Server 2017+ 原生支持的聚合函数,用于把多行字符串拼成一行;MySQL 和 SQLite 不支持该函数(MySQL 用 GROUP_CONCAT,SQLite 用 GROUP_CONCAT 或自定义扩展)。
核心写法是:STRING_AGG(expression, separator),其中 expression 是要拼接的列(或表达式),separator 是分隔符(必须是文本类型,不能为 NULL)。
常见错误:传入 NULL 分隔符会报错,比如 STRING_AGG(name, NULL) 在 PostgreSQL 中抛出 ERROR: separator must not be null;SQL Server 则允许省略 separator,默认用空字符串。
- PostgreSQL 要求显式指定 separator,且不可为
NULL - SQL Server 允许只写
STRING_AGG(col),此时 separator 默认为空字符串 - 想按特定顺序拼接?必须加
ORDER BY子句:如STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY id)
处理 NULL 值导致拼接结果异常
STRING_AGG 默认跳过 NULL 值——这通常是好事,但容易误以为“数据丢了”。比如 name 列有 'Alice'、NULL、'Bob',结果是 'Alice,Bob',不是 'Alice,,Bob'。
若需把 NULL 显式转为某个占位符(如 '(unknown)'),得提前用 COALESCE 或 CASE 处理:
SELECT STRING_AGG(COALESCE(name, '(unknown)'), ', ') FROM users;
注意:不能在 STRING_AGG 外层套 COALESCE(..., 'N/A') 来兜底,因为只要有一行非 NULL,聚合结果就不会是 NULL;只有整组全为 NULL(或无行)时,结果才是 NULL。
与 GROUP BY 配合时的常见陷阱
多数场景下,你不会只想把整张表拼成一行,而是按某字段分组后各自拼接——比如“每个部门的所有员工姓名”。这时 GROUP BY dept_id 必须包含所有非聚合列,否则报错。
典型错误写法:SELECT dept_id, STRING_AGG(name, '; ') FROM employees;(缺少 GROUP BY dept_id)
正确写法:
SELECT dept_id, STRING_AGG(name, '; ') WITHIN GROUP (ORDER BY name) FROM employees GROUP BY dept_id;
- PostgreSQL 和 SQL Server 都要求
GROUP BY显式列出所有非聚合列 -
WITHIN GROUP (ORDER BY ...)必须写在STRING_AGG后面,不能放在GROUP BY之后 - 如果漏掉
ORDER BY,拼接顺序由查询计划决定,不可预测
性能和大数据量下的注意事项
当单个分组要拼接成千上万行字符串时,STRING_AGG 可能成为瓶颈:PostgreSQL 会把全部值加载进内存再拼接;SQL Server 对结果长度有限制(默认最大 2GB,但实际受 varchar(max) 或 text 类型限制)。
实操建议:
- 提前用
LIMIT或子查询控制拼接行数(如只取前 100 个标签) - 避免在高并发 OLTP 查询中对大表直接用
STRING_AGG,考虑物化中间结果 - PostgreSQL 中若遇到
ERROR: out of memory,可调大work_mem,但治标不治本 - SQL Server 若结果超 8000 字节且目标列为
varchar(非varchar(max)),会被截断——务必确保接收列类型是varchar(max)或nvarchar(max)
最常被忽略的一点:不同数据库对返回类型的隐式推断规则不同。PostgreSQL 返回 text,SQL Server 返回与输入列一致的类型(可能截断),别依赖“看起来一样”。










