sql >> Database teknologi >  >> RDS >> PostgreSQL

XMLTABLE i PostgreSQL

Jeg har lige lavet en patch af Pavel Stěhule, der tilføjer XMLTABLE funktionalitet til PostgreSQL 10.  XMLTABLE er en meget nyttig funktion dikteret af SQL/XML-standarden, som lader dig omdanne dine XML-data til relationsform, så du kan blande dem med resten af ​​dine relationelle data. Denne funktion har mange anvendelser; fortsæt med at læse for nogle detaljer om det.

Sandsynligvis den mest interessante anvendelse af XMLTABLE er at udtrække data fra et eller andet XML-dokument for at indsætte i en relationstabel under ETL-behandling i databasen. Men XMLTABLE kan bruges on-the-fly på data, der er gemt i XML-kolonner, så når først dataene er i relationel form, kan du anvende enhver standardoperation, du ønsker, såsom at tilføje WHERE klausuler, laver sammenlægninger, joinforbindelser til andre tabeller og så videre.

Et simpelt eksempel

Lad os som et eksempel antage, at du administrerer en hotelkæde, og at dataene opbevares således:

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;

Med XMLTABLE , du kan omdanne dette til en relationelt formateret tabel bestående af værelsenumre og kapacitet, med annoteringer for hvert hotel i din kæde:

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 hotelnavn rum_id kapacitet kommentar
1 La Mancha 201 3 Fantastisk udsigt over kanalen
2 La Mancha 202 5 Et almindeligt rum
3 Valparaíso 201 2 Meget støjende
4 Valparaíso 202 2 Et almindeligt rum

Forklaring af syntaksen

Lad os studere forespørgslen ovenfor. XMLTABLE klausul skal gå i FROM del af forespørgslen. Vi har også hoteldata i FRA , som er det, der fører dataene ind i XMLTABLE .

Først PASSERING klausul er, hvor vi specificerer de XML-data, som vi ønsker at behandle. I dette tilfælde kommer dataene fra hotellerne kolonnen i hoteldata bord. Vi kalder dette dokumentudtrykket .

Lige før PASSERING klausul ser du et XPath-udtryk '/hotels/hotel/værelser/værelse' . Vi kalder dette det rækkegenererende udtryk eller bare rækkeudtrykket .

Vi har KOLONNER klausul næste, erklærer et par kolonner. For hver kolonne angiver vi en datatype samt en valgfri PATH klausul, som vi kalder kolonneudtrykket .

XMLTABLE 's operationsteori er, at rækkeudtrykket anvendes på dokumentudtrykket, idet dokumentet skæres i stykker for at generere rækker; for hver række, der genereres således, anvendes de forskellige kolonneudtryk for at opnå værdierne for hver kolonne.

Kolonneudtrykket er et XPath-udtryk, der henter en værdi, der starter fra XML for den aktuelle række. Hvis ikke PATH er angivet, så bruges selve kolonnenavnet som XPath-udtrykket. Bemærk, at i kolonnen hotel_name vi brugte en sti med "../ ", hvilket betyder at "gå op" i XML-dokumentet for at hente værdier fra "container"-objekterne i dokumentet. Vi kan også bruge xml PATH '.' i en række, hvilket giver os den fulde kilde-XML for den pågældende række.

Én kolonne kan markeres FOR ORDINALITET . Kolonnen er så af typen INTEGER , og er nummereret sekventielt for hver række hentet fra dokumentet. (Hvis der er flere inputdokumenter, f.eks. når du har flere rækker i en tabel, starter tælleren fra 1 for hvert nyt dokument).

Der er også en DEFAULT klausul. Hvis XPath for en kolonne ikke matcher en værdi for en bestemt række, så er DEFAULT værdi bruges.

Nogle af disse kolonner er blevet markeret som IKKE NULL . Hvis der ikke er nogen match og ingen DEFAULT klausulen er angivet (eller DEFAULT evalueres også til NULL ), vises en fejl.

Jeg vil ikke gå mere i detaljer med XPath, som er et kraftfuldt sprog, men jeg kan tilbyde XPath-artiklen på Wikipedia og det officielle anbefalingsdokument fra W3C som nyttige ressourcer.

Den fulde XMLTABLE-syntaks

Den dokumenterede syntakssynopsis er:

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

Bemærk, at dokumentudtrykket kan være en reference til en tabel, du har i FROM-sætningen, eller det kan være et komplet XML-dokument som en streng-literal. BY REF-klausulerne har ingen effekt; de er der for kompatibilitet med standarden og med andre databasesystemer.

Jeg har ikke dækket XMLNAMESPACES klausul i dette indlæg; Jeg overlader det til en fremtidig rate.

Anvendelse af SQL ovenpå

Som nævnt, når XMLTABLE har bearbejdet dataene til relationel form, kan du gøre hvad du vil ved hjælp af velkendte værktøjer. For eksempel, hvis du havde et andet XML-dokument med mere personale på hvert 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>$$);

Det er nemt at få de samlede lønninger for hver valuta, du skal betale på hvert 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 valuta sum
Valparaíso CLP 1200000
Valparaíso EUR 80000
La Mancha PTA 80000

Konklusion

I denne artikel har jeg dækket den nye funktion XMLTABLE vises i PostgreSQL version 10. Jeg tror XMLTABLE er en fantastisk funktion til at integrere eksterne data, og jeg håber, at du også finder den værdifuld. Test det venligst og rapporter eventuelle problemer, så vi kan løse dem inden den endelige udgivelse. Hvis du kan lide XMLTABLE , sørg for at lade os vide og efterlade en kommentar!


  1. isolering af en understreng i en streng før et symbol i SQL Server 2008

  2. SQL-forespørgsel - Sammenkædning af resultater i én streng

  3. Hvordan implementerer man én-til-en, én-til-mange og mange-til-mange relationer, mens man designer tabeller?

  4. HIbernate problem med Oracle Trigger til generering af id fra en sekvens