miércoles, mayo 23, 2007

XQuery-SQL Server 2005 - La guia

Hace tiempo que empecé a escribir sobre XQuery y apunté unos cuantos links útiles. Ahora vamos a dar una vuelta de tuerca y vamos a poner varios ejemplos.

Para ello vamos a usar un XML que tenga, más o menos variedad de cosillas: campos que se repiten, campos que no, elementos simples, complejos... para aplicar lo que aprendamos.

El XML podría ser el que sigue:






















Vale, ya tenemos el XML, vamos a empezar a hacer consultas basicas:

Antes de nada, vamos a ver la estructura que tienen las queries.

for $A in /Encuesta/Contenido/Pregunta
where $A/Respuesta = “SI”
return $A/Texto

Esta query nos va a buscar dentro de todas la preguntas. Va a filtrar las que cumplan que la respuesta es si, y nos va a devolver el enunciado (texto) de la pregunta

Abrimos una nueva Query en SQL Server y escribimos:

select @xmlText.query('for $A in /Encuesta/Contenido/Pregunta
where $A/Respuesta = ''SI''
return $A/Texto
')

Nos devolverá:
¿Le gusta el cine?
¿Le gusta el futbol?

Vamos a refinar un poco… Ahora solo queremos que nos devuelva el contenido, sin tags xml. La query seria:

select @xmlText.query('for $A in /Encuesta/Contenido/Pregunta
where $A/Respuesta = ''SI''
return $A/Texto
').value('(//Texto/text())[1]','VARCHAR(MAX)')

Al ejecutarlo, hay un problema: solo nos devuelve el primero de los campos… Esto nos vale SOLO cuando sabemos que sólo hay un campo. Por ejemplo, en nuestro caso sería una busqueda del nombre de un encuestado.

Vamos a solucionar el problemilla… Vamos a hacer dos técnicas:
Mostrar los dos en el mismo campo: Para ello vamos a hacer uso de una cuncion de XQuery: concat. Vamos a concatenar todas las preguntas.


select @xmlText.query('for $A in /Encuesta/Contenido/Pregunta
where $A/Respuesta = ''SI''
return concat($A/Texto[1]," - ")
')

Mejor, ahora nos devuelve las preguntas concatenadas…

Mostrar una fila por cada coincidencia: es posible que queramos mostrar una fila por pregunta, para ello haremos uso de la siguiente query. Necesitamos que el XML esté en una tabla, porque necesitamos hacer un CROSS. La query sería:

SELECT
cast(R.EncuestaDetails.query('.')
.value('(/Texto)[1]','VARCHAR(MAX)')
AS VARCHAR(100))
AS ClienteNm

FROM
[Encuesta] C
CROSS APPLY
C.[EncuestaXML].nodes('/Encuesta/Contenido/Pregunta)
AS R(EncuestaDetails)

Esto nos devolvería todas las preguntas (una por fila) que haya en los XML de la tabla.

Genial!!!! No?



No hay comentarios.: