sql >> Base de Datos >  >> RDS >> PostgreSQL

XMLTABLE en PostgreSQL

Acabo de enviar un parche de Pavel Stěhule que agrega la XMLTABLE funcionalidad a PostgreSQL 10.  XMLTABLE es una característica muy útil dictada por el estándar SQL/XML, que le permite convertir sus datos XML en formato relacional, para que pueda mezclarlos con el resto de sus datos relacionales. Esta característica tiene muchos usos; sigue leyendo para conocer algunos detalles al respecto.

Probablemente el caso de uso más interesante de XMLTABLE es extraer datos de algún documento XML para insertarlos en una tabla relacional, durante el procesamiento ETL en la base de datos. Sin embargo, XMLTABLE se puede usar sobre la marcha en datos almacenados en columnas XML, de modo que una vez que los datos están en forma relacional, puede aplicar cualquier operación estándar que desee, como agregar DÓNDE cláusulas, agregaciones, unión a otras tablas, etc.

Un ejemplo sencillo

Como ejemplo, supongamos que administra una cadena hotelera y que los datos se almacenan de la siguiente manera:

CREATE TABLE hoteldata AS SELECT xml
$$<hotels>
 <hotel id="mancha">
  <name>La Mancha</name>
  <rooms>
   <room id="201"><capacity>3</capacity><comment>Great view of the Channel</comment></room>
   <room id="202"><capacity>5</capacity></room>
  </rooms>
  <personnel>
   <person id="1025">
    <name>Ferdinando Quijana</name><salary currency="PTA">45000</salary>
   </person>
  </personnel>
 </hotel>
  <hotel id="valpo">
  <name>Valparaíso</name>
  <rooms>
   <room id="201"><capacity>2</capacity><comment>Very noisy</comment></room>
   <room id="202"><capacity>2</capacity></room>
  </rooms>
  <personnel>
   <person id="1026"><name>Katharina Wuntz</name><salary currency="EUR">50000</salary></person>
   <person id="1027"><name>Diego Velázquez</name><salary currency="CLP">1200000</salary></person>
  </personnel>
 </hotel>
</hotels>$$ AS hotels;

Con TABLAXML , puede convertir esto en una tabla con formato relacional que contenga números de habitaciones y capacidad, anotando para cada hotel de su cadena:

SELECT xmltable.*
  FROM hoteldata,
       XMLTABLE ('/hotels/hotel/rooms/room' PASSING hotels
                 COLUMNS
                    id FOR ORDINALITY,
                    hotel_name text PATH '../../name' NOT NULL,
                    room_id int PATH '@id' NOT NULL,
                    capacity int,
                    comment text PATH 'comment' DEFAULT 'A regular room'
                );
id nombre_del_hotel id_habitación capacidad comentario
1 La Mancha 201 3 Gran vista del Canal
2 La Mancha 202 5 Una habitación normal
3 Valparaíso 201 2 Muy ruidoso
4 Valparaíso 202 2 Una habitación normal

Explicando la sintaxis

Estudiemos la consulta anterior. La TABLAXML la cláusula debe ir en FROM parte de la consulta. También tenemos datos del hotel en el DESDE , que es lo que alimenta los datos en XMLTABLE .

Primero, el PASANDO cláusula es donde especificamos los datos XML que queremos procesar. En este caso, los datos provienen de los hoteles columna en los hoteldata mesa. Llamamos a esto la expresión del documento .

Justo antes del PASO cláusula, ve una expresión XPath '/hotels/hotel/rooms/room' . Llamamos a esto la expresión generadora de filas o simplemente la expresión de fila .

Tenemos las COLUMNAS cláusula siguiente, declarando algunas columnas. Para cada columna, indicamos un tipo de datos, así como una RUTA opcional. cláusula, que llamamos la expresión de columna .

TABLAXML La teoría de la operación es que la expresión de la fila se aplica a la expresión del documento, cortando el documento en partes para generar filas; para cada fila así generada, se aplican las distintas expresiones de columna para obtener los valores de cada columna.

La expresión de columna es una expresión XPath que obtiene un valor a partir del XML para la fila actual. Si no hay RUTA se especifica, el propio nombre de la columna se utiliza como la expresión XPath. Tenga en cuenta que en la columna hotel_name usamos una ruta que tenía “../ “, lo que significa “subir” en el documento XML para obtener valores de los objetos del “contenedor” en el documento. También podemos usar xml PATH '.' en una fila, lo que nos da el XML fuente completo para esa fila.

Una columna se puede marcar PARA ORDINALIDAD . La columna es entonces de tipo INTEGER , y se numera secuencialmente para cada fila obtenida del documento. (Si hay varios documentos de entrada, como cuando tiene varias filas en una tabla, el contador comienza desde 1 para cada documento nuevo).

También hay un DEFAULT cláusula. Si el XPath para una columna no coincide con un valor para una determinada fila, entonces DEFAULT se utiliza el valor.

Algunas de estas columnas se han marcado como NOT NULL . Si no hay ninguna coincidencia ni DEFAULT se especifica la cláusula (o el DEFAULT también se evalúa como NULL ), se lanza un error.

No entraré en más detalles sobre XPath, que es un lenguaje poderoso, pero puedo ofrecer el artículo de XPath en Wikipedia y el documento oficial de recomendaciones del W3C como recursos útiles.

La sintaxis completa de XMLTABLE

La sinopsis de sintaxis documentada es:

xmltable( [XMLNAMESPACES(namespace uri AS namespace name[, ...])] row_expression PASSING [BY REF] document_expression [BY REF] COLUMNS name { type [PATH column_expression] [DEFAULT expr] [NOT NULL | NULL] | FOR ORDINALITY } [, ...] )

Tenga en cuenta que la expresión del documento puede ser una referencia a alguna tabla que tenga en la cláusula FROM, o puede ser un documento XML completo como un literal de cadena. Las cláusulas BY REF no tienen ningún efecto; están allí para la compatibilidad con el estándar y con otros sistemas de bases de datos.

No he cubierto los XMLNAMESPACES cláusula en esta publicación; Lo dejo para una próxima entrega.

Aplicando SQL en la parte superior

Como se mencionó, una vez que XMLTABLE ha procesado los datos en forma relacional, puede hacer lo que quiera usando herramientas bien conocidas. Por ejemplo, si tuviera otro documento XML con más personal en cada hotel,

INSERT INTO hoteldata VALUES (xml
$$<hotels> 
 <hotel id="mancha">
  <name>La Mancha</name>
  <personnel>
   <person id="1028">
    <name>Sancho Panza</name><salary currency="PTA">35000</salary>
   </person>
  </personnel>
 </hotel>
 <hotel id="valpo">
  <name>Valparaíso</name>
  <personnel>
   <person id="1029"><name>Kurt Werner</name><salary currency="EUR">30000</salary></person>
  </personnel>
 </hotel>
</hotels>$$);

Es fácil obtener los salarios totales para cada moneda que debe pagar en cada hotel,

  SELECT hotel, currency, sum(salary)
    FROM hoteldata,
XMLTABLE ('/hotels/hotel/personnel/person' PASSING hotels
       COLUMNS hotel text PATH '../../name' NOT NULL,
               salary integer PATH 'salary' NOT NULL,
               currency text PATH 'salary/@currency' NOT NULL
) GROUP BY hotel, currency;
hotel moneda suma
Valparaíso CLP 1200000
Valparaíso EUR 80000
La Mancha PTA 80000

Conclusión

En este artículo, he cubierto la nueva característica XMLTABLE para aparecer en la versión 10 de PostgreSQL. Creo que XMLTABLE es una gran función para integrar datos externos, y espero que también la encuentre valiosa. Pruébelo e informe cualquier problema, para que podamos resolverlo antes del lanzamiento final. Si te gusta XMLTABLE , ¡asegúrate de hacérnoslo saber dejando un comentario!