STRING_AGG y STRING_SPLIT: reunir y separar texto delimitado
Algunas salidas necesitan presentar varios valores en una sola cadena; otras reciben una cadena con elementos delimitados que debemos convertir en filas. STRING_AGG reúne y STRING_SPLIT separa.
Son herramientas útiles en los límites del sistema, pero una lista dentro de una columna no sustituye una relación correctamente modelada.
Reunir valores por grupo
SELECT
p.IdCategoria,
STRING_AGG(
CONVERT(NVARCHAR(MAX), p.Nombre),
N', '
) WITHIN GROUP (ORDER BY p.Nombre) AS Productos
FROM dbo.Producto AS p
WHERE p.Activo = 1
GROUP BY p.IdCategoria;
STRING_AGG concatena los nombres de cada categoría y coloca el separador entre valores. WITHIN GROUP establece el orden dentro de la cadena; el ORDER BY exterior, si existe, ordena las filas finales.
Los valores NULL se omiten junto con su separador. Si queremos representar su ausencia, aplicamos antes COALESCE o ISNULL.
Separar una lista
DECLARE @Ids NVARCHAR(100) = N'1, 3, 5';
SELECT
TRY_CONVERT(INT, TRIM(s.value)) AS IdProducto
FROM STRING_SPLIT(@Ids, N',') AS s
WHERE TRY_CONVERT(INT, TRIM(s.value)) IS NOT NULL;
Cada fragmento se devuelve como una fila llamada value. Limpiar y convertir de forma segura evita que un valor inesperado detenga toda la consulta.
El orden de salida de STRING_SPLIT no está garantizado. Si el orden original importa y utilizamos SQL Server 2022 o posterior, podemos solicitar una columna ordinal:
SELECT
s.ordinal,
TRIM(s.value) AS Valor
FROM STRING_SPLIT(N'rojo,verde,azul', N',', 1) AS s
ORDER BY s.ordinal;
El tercer argumento debe ser una constante y no está disponible en versiones anteriores.
Compatibilidad
STRING_SPLIT requiere un nivel de compatibilidad de base de datos 130 o superior. STRING_AGG está disponible desde SQL Server 2017; el orden mediante WITHIN GROUP depende del nivel de compatibilidad admitido.
Cuando un script debe funcionar en instalaciones antiguas, comprobamos versión y nivel de compatibilidad en lugar de asumir que la función existe.
Longitud del resultado
El tipo de la expresión agregada influye en el tipo y la longitud del resultado. Convertir de forma explícita a NVARCHAR(MAX) evita límites inesperados cuando concatenamos muchos valores, aunque también debemos controlar el tamaño que realmente puede consumir el cliente.
Cuándo no utilizar una lista delimitada
Para filtrar cientos o miles de identificadores enviados por una aplicación, un parámetro con valor de tabla suele ser más claro y eficiente. Para almacenar relaciones, usamos una tabla relacionada y no una cadena separada por comas.
Reservamos estas funciones para presentación, intercambio acotado o datos que llegan legítimamente como texto.
Qué conviene comprobar
Revisamos delimitador, espacios, elementos vacíos, conversión, duplicados, intercalación y tamaño. Si los valores pueden contener el mismo delimitador, necesitamos un formato estructurado como JSON, no una división ingenua.
Relacionado con
TRIM: elimina espacios alrededor de cada fragmento.TRY_CONVERT: descarta o identifica valores inválidos sin detener la consulta.GROUP BY: produce una cadena agregada por cada grupo.- JSON: representa listas y objetos con una estructura explícita.