jueves, 19 de febrero de 2015

LEER XML EN SQL (SELECT XML)

Buenos Días. Volviendo de vacaciones y compartiendo lo siguiente.

Muchas veces nos encontramos con situaciones que las soluciones suelen ser algo extravagantes, en esta entrada compartiré un tip que luego estará en el esquema del curso, ¿de qué se trata?, leer los XML como una tabla.

XML en SQL contiene muy buenas ventajas para quienes lo usen adecuadamente, es un tipo de variable especifico, es nativo, es de fácil declaración del lado de la programación, es flexible para trabajar, etc…

Entonces la pregunta es, a fines prácticos ¿en que nos puede ayudar?, enumero algunas situaciones.

  • Envió de múltiples variables desde un sistema a la base de datos
  • Envió de tablas desde un sistema a la base de datos en un esquema altamente entendible
  • Recepción de servicios SOAP y operarlo directamente sobre el SQL sin pasar por ningún tipo de software externo, parsing, etc… ¿dije SOAP?, SI… En algún momento les mostrare como consumir servicios desde SQL y que configuración adicional tenemos que incorporar, pero eso lo dejaremos para más adelante :)
Estos son algunos de los usos posibles del XML sobre SQL, y sin duda tendremos infinidades de casos en que usarlo será el camino más óptimo a nuestro problema, y sin duda, nos puede ayudar a brindar una solución mucho más profesional.

Obviare la explicación de los que es una cadena en formato XML, por lo tanto, lo explicare muy muy simple… Es un METALENGUAJE, que permite etiquetar y organizar los elementos, muchos archivos y sistemas utilizan XML para trabajar, inclusive una extensión tan popular como el SVG se apoya sobre XML para definirle las características.
Empecemos…

Utilizaremos para este ejercicio un ejemplo escrito para poder trabajar con el, donde definiremos una variable XML, la cargaremos y luego realizamos la lectura del mismo, tenemos muchas formas de leer XML en SQL, les mostrare unas de tantas, para mi gusto la mas simple, pero eso es solo una apreciación mía.
Lo primero que haremos es crear la variable XML y cargarla con contenido.

DECLARE @VARIABLE_XML XML

SET @VARIABLE_XML = '<tabla1>
<fila><campo1>216000</campo1><campo2>3</campo2></fila>
<fila><campo1>217000</campo1><campo2>4</campo2></fila>
<fila><campo1>218000</campo1><campo2>5</campo2></fila>
<fila><campo1>219000</campo1><campo2>6</campo2></fila>
</tabla1>'


Como se puede apreciar, existe un tipo de variable en SQL que es XML, y al mismo luego le incorporamos un valor XML, en este caso muy sencillo, se puede apreciar que es un XML donde pasamos una TABLA1, el mismo esta compuestos por “FILA”, y luego está dividido en “CAMPO”, si nos fijamos cada “CAMPO” tiene valores, vamos a aprender a leerlos!!!

SELECT 
TABLA1.ID.value('campo1[1]','INT') AS CAMPO_1,
 TABLA1.ID.value('campo2[1]','NVARCHAR(4000)') AS CAMPO_2
  FROM @VARIABLE_XML.nodes('/tabla1/fila') as TABLA1(ID) 

Bien, en la anterior consulta se puede apreciar la forma de leerlo, esta es un tipo de consulta utilizando Xquery en SQL, el mismo funciona por defecto, por tanto no necesitamos de realizar ningún tipo de configuración adicional.

Explicando la query anterior, esto funciona de la siguiente forma:
Como se puede ver es una consulta SELECT clásica, donde seleccionamos los valores de un FROM, en este caso el FROM es un XML, donde instanciamos la variable XML, y luego buscamos los NODOS, nosotros por el tipo de estructura del XML llegamos hasta el nodo FILA, y luego una vez instanciado hasta el nodo fila, generamos un ALIAS y dentro del mismo le generamos una columna (lo que esta entre paréntesis), no detallare mucho sobre porque se define de esta forma, pero SQL devuelve una especie de TABLA en memoria.

Vamos ahora al SELECT, aquí como se puede ver, la estructura es, TABLA.COLUMNA.VALOR([NODO XML], [TIPO DE VALOR]) as NOMBRE_COLUMNA.

Esto es, llamamos a la tabla y al valor de la columna, y entre paréntesis instanciamos el valor que queremos utilizar dentro de la estructura XML, en estos casos CAMPO1 y CAMPO2, y luego muy importante tenemos que definir qué tipo de dato es, si es un INT, VARCHAR, DATETIME, etc…

Muy bien!, sé que puede parecer un poco confuso al principio, pero es cuestión de practicarlo un poco y veremos que es muy práctico. A continuación pondré un ejemplo un poco más complejo en el que podemos observar que se pueden realizar cruces sin ningún tipo de problema, tanto dentro del XML como con tablas externas, en este caso estoy enviando dos tablas dentro del mismo XML y cruzándolas en la consulta.
 
DECLARE @VARIABLE_XML XML

SET @VARIABLE_XML = '<tabla1>
<fila><campo1>216000</campo1><campo2>3</campo2></fila>
<fila><campo1>217000</campo1><campo2>4</campo2></fila>
<fila><campo1>218000</campo1><campo2>5</campo2></fila>
<fila><campo1>219000</campo1><campo2>6</campo2></fila>
</tabla1>
<tabla2>
<fila><campo1>316000</campo1><campo2>3</campo2></fila>
<fila><campo1>317000</campo1><campo2>4</campo2></fila>
<fila><campo1>318000</campo1><campo2>5</campo2></fila>
<fila><campo1>319000</campo1><campo2>6</campo2></fila>
</tabla2>'


SELECT  TABLA1.ID.value('campo1[1]','INT') AS TABLA1_CAMPO_1,
   TABLA1.ID.value('campo2[1]','NVARCHAR(4000)') AS TABLA1_CAMPO_2,
   TABLA2.ID.value('campo1[1]','NVARCHAR(4000)') AS TABLA2_CAMPO_1
    FROM  @VARIABLE_XML.nodes('/tabla1/fila') as TABLA1(ID)
INNER JOIN  @VARIABLE_XML.nodes('/tabla2/fila') as TABLA2(ID) 
 ON
  TABLA1.ID.value('campo2[1]','NVARCHAR(4000)') = TABLA2.ID.value('campo2[1]','NVARCHAR(4000)')

Excelente!, invito a probar la siguiente consulta para que vean el comportamiento  del mismo!!!

Bueno eso es todo, cualquier consulta no duden en preguntar.

Espero que les sea de mucha utilidad, hasta la próxima.