PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

XMLTABLE in PostgreSQL

Ich habe gerade einen Patch von Pavel Stěhule hochgeladen, der die XMLTABLE hinzufügt Funktionalität zu PostgreSQL 10.  XMLTABLE ist eine sehr nützliche Funktion, die vom SQL/XML-Standard vorgegeben wird und mit der Sie Ihre XML-Daten in relationale Form umwandeln können, sodass Sie sie mit den übrigen relationalen Daten mischen können. Diese Funktion hat viele Verwendungsmöglichkeiten; Lesen Sie weiter, um mehr darüber zu erfahren.

Der wohl interessanteste Anwendungsfall von XMLTABLE besteht darin, Daten aus einem XML-Dokument zu extrahieren, um sie während der datenbankinternen ETL-Verarbeitung in eine relationale Tabelle einzufügen. Allerdings XMLTABLE kann on-the-fly auf Daten verwendet werden, die in XML-Spalten gespeichert sind, sodass Sie, sobald die Daten in relationaler Form vorliegen, alle gewünschten Standardoperationen anwenden können, wie z. B. das Hinzufügen von WHERE Klauseln, Aggregationen, Verknüpfungen mit anderen Tabellen und so weiter.

Ein einfaches Beispiel

Nehmen wir als Beispiel an, Sie verwalten eine Hotelkette und die Daten werden folgendermaßen gespeichert:

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;

Mit XMLTABLE , können Sie dies in eine relational formatierte Tabelle umwandeln, die aus Zimmernummern und Kapazitäten besteht und für jedes Hotel in Ihrer Kette Anmerkungen enthält:

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 Hotelname room_id Kapazität Kommentar
1 La Mancha 201 3 Tolle Aussicht auf den Ärmelkanal
2 La Mancha 202 5 Ein normaler Raum
3 Valparaiso 201 2 Sehr laut
4 Valparaiso 202 2 Ein normaler Raum

Erläuterung der Syntax

Sehen wir uns die obige Abfrage an. Die XMLTABLE -Klausel muss in FROM stehen Teil der Abfrage. Wir haben auch Hoteldaten im VON , was die Daten in XMLTABLE einspeist .

Zuerst das PASSING -Klausel geben wir die XML-Daten an, die wir verarbeiten möchten. In diesem Fall stammen die Daten von den Hotels Spalte in den Hoteldaten Tisch. Wir nennen dies den Dokumentausdruck .

Kurz vor dem PASSING -Klausel sehen Sie einen XPath-Ausdruck '/hotels/hotel/rooms/room' . Wir nennen dies den zeilengenerierenden Ausdruck oder nur der Zeilenausdruck .

Wir haben die COLUMNS Klausel nächste, die einige Spalten deklariert. Für jede Spalte geben wir einen Datentyp sowie einen optionalen PFAD an -Klausel, die wir den Spaltenausdruck nennen .

XMLTABLE Die Operationstheorie besteht darin, dass der Zeilenausdruck auf den Dokumentausdruck angewendet wird, wodurch das Dokument in Stücke geschnitten wird, um Zeilen zu erzeugen; für jede so erzeugte Zeile werden die verschiedenen Spaltenausdrücke angewendet, um die Werte für jede Spalte zu erhalten.

Der Spaltenausdruck ist ein XPath-Ausdruck, der einen Wert abruft, der aus dem XML für die aktuelle Zeile beginnt. Wenn kein PATH angegeben ist, wird der Spaltenname selbst als XPath-Ausdruck verwendet. Beachten Sie das in der Spalte hotel_name wir haben einen Pfad mit „../ “, was im XML-Dokument „nach oben gehen“ bedeutet, um Werte aus den „Container“-Objekten im Dokument abzurufen. Wir können auch xml PATH '.' verwenden in einer Reihe, was uns die vollständige Quell-XML für diese Reihe gibt.

Eine Spalte kann FOR ORDINALITY markiert werden . Die Spalte ist dann vom Typ INTEGER , und wird fortlaufend für jede aus dem Dokument erhaltene Zeile nummeriert. (Wenn mehrere Eingabedokumente vorhanden sind, z. B. wenn Sie mehrere Zeilen in einer Tabelle haben, beginnt der Zähler für jedes neue Dokument bei 1).

Es gibt auch einen STANDARD Klausel. Wenn der XPath für eine Spalte nicht mit einem Wert für eine bestimmte Zeile übereinstimmt, dann wird der DEFAULT Wert verwendet.

Einige dieser Spalten wurden als NOT NULL gekennzeichnet . Wenn es keine Übereinstimmung gibt, und kein DEFAULT -Klausel angegeben ist (oder die DEFAULT wird auch zu NULL ausgewertet ), wird ein Fehler ausgegeben.

Ich werde nicht näher auf XPath eingehen, das eine mächtige Sprache ist, aber ich kann den XPath-Artikel in Wikipedia und das offizielle Empfehlungsdokument des W3C als nützliche Ressourcen anbieten.

Die vollständige XMLTABLE-Syntax

Die dokumentierte Syntaxzusammenfassung lautet:

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

Beachten Sie, dass der Dokumentausdruck ein Verweis auf eine Tabelle sein kann, die Sie in der FROM-Klausel haben, oder dass es sich um ein vollständiges XML-Dokument als Zeichenfolgenliteral handeln kann. Die BY REF-Klauseln haben keine Wirkung; sie dienen der Kompatibilität mit dem Standard und mit anderen Datenbanksystemen.

Ich habe die XMLNAMESPACES nicht behandelt Klausel in diesem Beitrag; Ich hebe das für eine zukünftige Rate auf.

SQL oben anwenden

Wie bereits erwähnt, können Sie, sobald XMLTABLE die Daten in relationaler Form verarbeitet hat, mit bekannten Tools tun, was Sie wollen. Wenn Sie beispielsweise in jedem Hotel ein anderes XML-Dokument mit mehr Personal hätten,

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 ist einfach, die Gesamtgehälter für jede Währung zu erhalten, die Sie in jedem Hotel bezahlen müssen,

  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 Währung Summe
Valparaiso CLP 1200000
Valparaíso EUR 80000
La Mancha PTA 80000

Schlussfolgerung

In diesem Artikel habe ich das neue Feature XMLTABLE behandelt in PostgreSQL Version 10 erscheinen. Ich denke XMLTABLE ist ein großartiges Feature zur Integration externer Daten, und ich hoffe, Sie finden es auch wertvoll. Bitte testen Sie es und melden Sie Probleme, damit wir sie vor der endgültigen Veröffentlichung beheben können. Wenn Sie XMLTABLE mögen , lassen Sie es uns unbedingt wissen und hinterlassen Sie einen Kommentar!