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.