Saltar al contenido

Explique qué hace “for xml path(”), TYPE) .value(‘.’, ‘NVARCHAR(MAX)’)” en este código

Te recomendamos que pruebes esta respuesta en un entorno controlado antes de enviarlo a producción, un saludo.

Solución:

Una técnica común para el agregado string concatenación antes de SQL Server 2017 usa métodos de tipo de datos XML junto con STUFF para eliminar el delimitador adicional. En SQL Server 2017 y versiones posteriores, STRING_AGG hace que esta tarea sea mucho más limpia y fácil. El STRING_AGG equivalente:

select @colsUnpivot = STRING_AGG(quotename (C.name),',')
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')

Los componentes de la técnica de expresión XML para agregado string concatenación son las siguientes.

Esta subconsulta generará un conjunto de resultados con una fila por columna en la tabla de origen con una coma antes de cada nombre de columna:

select ',' + quotename (C.name)
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')

Resultado de ejemplo:

,[column1]
,[column2]
,[column3]

Agregando el FOR XML PATH(''), TYPE convierte estas filas en un solo nodo de texto XML fuertemente tipado con las filas concatenadas, lo que permite métodos XML como value para ser utilizado en el tipo:

select ',' + quotename (C.name)
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')
for xml path(''), TYPE

Resultado (tipo XML):

,[column1],[column2],[column3]

Invocando el método value('.', 'NVARCHAR(MAX)') en ese nodo XML convierte el nodo XML en un nvarchar (MAX) string. El value El método de tipo de datos XML toma una expresión XQuery con '.' que representa el nodo actual (solo el nodo aquí) y el segundo argumento es el tipo de datos SQL deseado que se devolverá.

SELECT
         (select ',' + quotename (C.name)
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')
          for xml path(''), TYPE).value('.', 'NVARCHAR(MAX)')

Resultado (nvarchar(MAX)):

,[column1],[column2],[column3]

Finalmente, la función STUFF elimina el delimitador principal extraño del string. Hay un error en su ejemplo original; la longitud debe ser 1 en lugar de 8 para que solo se elimine la coma:

SELECT
         STUFF((select ',' + quotename (C.name)
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')
          for xml path(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')

Resultado final (nvarchar(MAX)):

[column1],[column2],[column3]

A veces veo que la gente omite el , TYPE).value('.', 'NVARCHAR(MAX)') al utilizar esta técnica. El problema con eso es que algunos caracteres deben escaparse con referencias a entidades XML (por ejemplo, comillas) para que el resultado string no será como se esperaba en ese caso.

EDITAR:

Incorporando la recomendación de uso de Mister Magoo (./text())[1] en lugar de solo . como especificación del nodo, la consulta a continuación mejorará el rendimiento con grandes conjuntos de datos.

SELECT
         STUFF((select ',' + quotename (C.name)
          from sys.columns c
          where c.object_id = OBJECT_ID('dbo.result2')
          for xml path(''), TYPE).value('(./text())[1]', 'NVARCHAR(MAX)'),1,1,'');

Como dijo Dan, pero también…

Acostúmbrese a usar el nodo text() en valores xml, no hará mucha diferencia en un conjunto de resultados pequeño, pero no veo ninguna razón para NO usarlo, y realmente verá un beneficio en conjuntos de datos más grandes. .

La sección roja es dolorosa y se puede evitar mediante el uso de (./text())[1]

Compara planes con el uso del nodo text().

valoraciones y comentarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *