SQL Server 2022需兼容级别≥160才支持STRING_AGG,且必须配合GROUP BY和WITHIN GROUP(ORDER BY ...)使用,分隔符不可为NULL,非字符串字段须显式转换。

确认你的SQL Server 2022真支持STRING_AGG
别光看安装界面写着“2022”就开写,STRING_AGG在SQL Server中是按兼容级别激活的,不是按产品版本自动启用。运行这两条语句才能实锤:
SELECT @@VERSION;——输出必须含 Microsoft SQL Server 2022(不是 16.x 这类内部代号)
SELECT DATABASEPROPERTYEX(DB_NAME(), 'CompatibilityLevel');——结果必须 ≥ 160
如果第二条返回 150(2019)或更低,哪怕版本是2022,STRING_AGG也会被当作不存在。得先执行:ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 160;
STRING_AGG必须配GROUP BY,不能裸用
它和 COUNT()、SUM() 是同一类聚合函数,没有分组维度,SQL Server 直接拒绝执行。
常见错误写法:SELECT STRING_AGG(name, ', ') FROM users; → 报错 STRING_AGG is not allowed in the context
正确姿势分两类:
- 按业务字段分组:
SELECT dept_id, STRING_AGG(name, '; ') FROM users GROUP BY dept_id; - 全表拼成一行:SQL Server 不支持
GROUP BY (),得绕一下:SELECT STRING_AGG(name, ', ') FROM (SELECT name FROM users) t GROUP BY (SELECT NULL);
WITHIN GROUP (ORDER BY ...)不是可选,是强制
不加 WITHIN GROUP,结果顺序完全不可控——哪怕表有主键、聚集索引,下次查询可能就变。这不是性能问题,是语义缺失。
正确写法:STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY hire_date DESC)
但要注意限制:
-
ORDER BY里的字段必须出现在GROUP BY子句中,或为聚合表达式(如MIN(hire_date)) - 不能用列别名:
SELECT dept AS d, STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY d)→ 报错 - 非字符串字段要显式转换:
STRING_AGG(CAST(id AS VARCHAR), ', '),否则可能隐式转换失败
分隔符不能为NULL,空字符串可以但要小心
STRING_AGG(name, NULL) 会直接报错:separator must not be null
STRING_AGG(name, '') 合法,但拼出来就是连在一起的字符串(如 abc),中间无任何分隔。若想换行,得用:STRING_AGG(name, CHAR(13)+CHAR(10))
另外注意:NULL 值默认被忽略,不会留空位也不会加多余分隔符。如果需要占位(比如显示 张三,,李四),得提前用 ISNULL(name, '') 处理。

















