MySQL 5.7 用 GROUP_CONCAT() 拼接字符串,需注意默认长度限制1024、去重排序语法、NULL处理;PostgreSQL 用 STRING_AGG() 要防NULL致全空;SQL Server 2017+ 支持 STRING_AGG(),旧版用 FOR XML;SQLite 的 group_concat() 不支持排序且分隔符限两字符。

MySQL 5.7 用 GROUP_CONCAT() 拼接字符串
MySQL 5.7 及更早版本不支持 STRING_AGG(),必须用 GROUP_CONCAT()。它默认以逗号分隔,但有隐式长度限制(group_concat_max_len 默认仅 1024 字符),超长会被截断且无提示。
- 查当前限制:
SELECT @@group_concat_max_len; - 临时调高(会话级):
SET SESSION group_concat_max_len = 1000000; - 拼接时去重加排序:
GROUP_CONCAT(DISTINCT name ORDER BY name SEPARATOR ', ') - 空值会被忽略,若需显示为
'NULL',得先用IFNULL(name, 'NULL')转换
PostgreSQL 用 STRING_AGG() 处理 NULL 和分隔符
STRING_AGG() 是 PostgreSQL 的标准方案,但对 NULL 值敏感:只要任意一个值为 NULL,整个聚合结果就变成 NULL,这点和 MySQL 不同,容易漏掉数据。
- 安全拼接(跳过 NULL):
STRING_AGG(COALESCE(name, ''), ', ') FILTER (WHERE name IS NOT NULL) - 想把 NULL 显式转成字符串:
STRING_AGG(COALESCE(name, 'N/A'), ', ') - 注意顺序:必须用
ORDER BY子句控制拼接顺序,否则结果不稳定,例如STRING_AGG(name, ', ') ORDER BY name
SQL Server 2017+ 推荐 STRING_AGG(),旧版用 FOR XML
SQL Server 2017 起原生支持 STRING_AGG(),但早期版本(如 2016)只能靠 FOR XML PATH('') 曲线救国,写法绕且易出错。
- 新版本直接用:
STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY id)——WITHIN GROUP必须写,不能省略 - 旧版本替代方案:
STUFF((SELECT ', ' + name FROM t2 WHERE t2.group_id = t1.group_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') -
STUFF()用来删开头多余的', ',漏掉会导致结果以逗号开头
SQLite 需手动实现,用 group_concat() 但不支持排序
SQLite 内置的 group_concat() 函数最简陋:没有 ORDER BY 支持,拼接顺序取决于查询执行时的行序,不可控;也不接受自定义分隔符以外的参数。
- 基本用法只有:
group_concat(name, '; ')—— 分隔符最多两个字符,多于两个会被截断 - 要保证顺序?只能提前子查询排序:
SELECT group_concat(name, '; ') FROM (SELECT name FROM t ORDER BY sort_order) - 遇到 NULL 会跳过,但不会报错;若字段含单引号或双引号,拼接后不会自动转义,可能破坏后续解析

















