PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

XMLTABLE dans PostgreSQL

Je viens de commiter un patch de Pavel Stěhule qui ajoute le XMLTABLE fonctionnalité à PostgreSQL 10.  XMLTABLE est une fonctionnalité très utile dictée par la norme SQL/XML, qui vous permet de transformer vos données XML en forme relationnelle, afin que vous puissiez les mélanger avec le reste de vos données relationnelles. Cette fonctionnalité a de nombreuses utilisations; continuez à lire pour plus de détails à ce sujet.

Probablement le cas d'utilisation le plus intéressant de XMLTABLE consiste à extraire des données d'un document XML à insérer dans une table relationnelle, lors du traitement ETL dans la base de données. Cependant, XMLTABLE peut être utilisé à la volée sur des données stockées dans des colonnes XML, de sorte qu'une fois que les données sont sous forme relationnelle, vous pouvez appliquer toutes les opérations standard que vous souhaitez, telles que l'ajout de WHERE clauses, faire des agrégations, joindre à d'autres tables, etc.

Un exemple simple

A titre d'exemple, supposons que vous administrez une chaîne hôtelière, et que les données soient stockées ainsi :

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;

Avec XMLTABLE , vous pouvez transformer cela en un tableau au format relationnel composé des numéros et de la capacité des chambres, annotant pour chaque hôtel de votre chaîne :

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'
                );
identifiant nom_hôtel room_id capacité commentaire
1 La Manche 201 3 Superbe vue sur la chaîne
2 La Manche 202 5 Une salle normale
3 Valparaiso 201 2 Très bruyant
4 Valparaiso 202 2 Une salle normale

Expliquer la syntaxe

Étudions la requête ci-dessus. Le XMLTABLE la clause doit aller dans le FROM partie de la requête. Nous avons également hoteldata dans le DE , qui alimente les données dans XMLTABLE .

Tout d'abord, le PASSAGE La clause est l'endroit où nous spécifions les données XML que nous voulons traiter. Dans ce cas, les données proviennent des hôtels colonne dans les hoteldata table. Nous appelons cela l'expression du document .

Juste avant le PASSAGE clause vous voyez une expression XPath '/hotels/hotel/rooms/room' . Nous appelons cela l'expression génératrice de lignes ou simplement l'expression de ligne .

Nous avons les COLONNES clause suivante, en déclarant quelques colonnes. Pour chaque colonne, nous indiquons un type de données ainsi qu'un PATH facultatif clause, que nous appelons l'expression de colonne .

XMLTABLE La théorie de fonctionnement de est que l'expression de ligne est appliquée à l'expression de document, en découpant le document en morceaux pour générer des lignes ; pour chaque ligne ainsi générée, les différentes expressions de colonne sont appliquées pour obtenir les valeurs de chaque colonne.

L'expression de colonne est une expression XPath qui obtient une valeur à partir du XML pour la ligne actuelle. Si aucun CHEMIN est spécifié, le nom de la colonne lui-même est utilisé comme expression XPath. Notez que dans la colonne hotel_name nous avons utilisé un chemin ayant "../ ", ce qui signifie "monter" dans le document XML pour récupérer les valeurs des objets "conteneur" dans le document. Nous pouvons également utiliser xml PATH '.' dans une ligne, ce qui nous donne le XML source complet pour cette ligne.

Une colonne peut être marquée POUR ORDINALITE . La colonne est alors de type INTEGER , et est numéroté séquentiellement pour chaque ligne obtenue à partir du document. (S'il y a plusieurs documents d'entrée, comme lorsque vous avez plusieurs lignes dans un tableau, le compteur commence à 1 pour chaque nouveau document).

Il y a aussi un DEFAULT clause. Si le XPath d'une colonne ne correspond pas à une valeur pour une certaine ligne, alors le DEFAULT valeur est utilisée.

Certaines de ces colonnes ont été marquées comme NOT NULL . S'il n'y a pas de correspondance et pas de DEFAULT la clause est spécifiée (ou la DEFAULT est également évalué à NULL ), une erreur est renvoyée.

Je n'entrerai pas dans les détails de XPath, qui est un langage puissant, mais je peux proposer l'article XPath sur Wikipedia et le document de recommandation officiel du W3C comme ressources utiles.

La syntaxe XMLTABLE complète

Le synopsis de syntaxe documenté est :

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 } [, ...] )

Notez que l'expression de document peut être une référence à une table que vous avez dans la clause FROM, ou il peut s'agir d'un document XML complet en tant que littéral de chaîne. Les clauses BY REF n'ont aucun effet; ils sont là pour la compatibilité avec la norme et avec d'autres systèmes de bases de données.

Je n'ai pas couvert les XMLNAMESPACES clause dans ce post ; Je laisse ça pour un prochain versement.

Appliquer SQL par dessus

Comme mentionné, une fois que XMLTABLE a traité les données sous forme relationnelle, vous pouvez faire ce que vous voulez en utilisant des outils bien connus. Par exemple, si vous aviez un autre document XML avec plus de personnel dans chaque hôtel,

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>$$);

Il est facile d'obtenir le salaire total pour chaque devise que vous devez payer dans chaque hôtel,

  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;
hôtel devise somme
Valparaiso CLP 1200000
Valparaiso EUR 80000
La Manche PTA 80000

Conclusion

Dans cet article, j'ai couvert la nouvelle fonctionnalité XMLTABLE pour apparaître dans PostgreSQL version 10. Je pense que XMLTABLE est une excellente fonctionnalité pour intégrer des données externes, et j'espère que vous la trouverez également utile. Veuillez le tester et signaler tout problème, afin que nous puissions les résoudre avant la version finale. Si vous aimez XMLTABLE , assurez-vous de nous le faire savoir en laissant un commentaire !