sql >> Databáze >  >> RDS >> PostgreSQL

XMLTABLE v PostgreSQL

Právě jsem zveřejnil patch od Pavla Stěhuleho, který přidává XMLTABLE funkčnost do PostgreSQL 10.  XMLTABLE je velmi užitečná funkce diktovaná standardem SQL/XML, která vám umožňuje převést data XML do relační podoby, abyste je mohli smíchat se zbytkem relačních dat. Tato funkce má mnoho využití; Pokračujte ve čtení pro některé podrobnosti.

Pravděpodobně nejzajímavější případ použití XMLTABLE je extrahovat data z nějakého dokumentu XML a vložit je do relační tabulky během zpracování ETL v databázi. Nicméně XMLTABLE lze za běhu použít na data uložená ve sloupcích XML, takže jakmile budou data v relační formě, můžete použít libovolné standardní operace, jako je přidání KAM klauzule, provádění agregací, připojování k jiným tabulkám a tak dále.

Jednoduchý příklad

Předpokládejme například, že spravujete hotelový řetězec a že data jsou uložena takto:

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;

Pomocí XMLTABLE , můžete to přeměnit na relačně formátovanou tabulku sestávající z číslí pokojů a kapacity s poznámkami pro každý hotel ve vašem řetězci:

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 název_hotelu id_místnosti kapacita komentář
1 La Mancha 201 3 Skvělý pohled na kanál
2 La Mancha 202 5 Běžná místnost
3 Valparaíso 201 2 Velmi hlučné
4 Valparaíso 202 2 Běžná místnost

Vysvětlení syntaxe

Pojďme si prostudovat výše uvedený dotaz. XMLTABLE klauzule musí být v FROM část dotazu. Máme také hotelová data v OD , což je to, co dodává data do XMLTABLE .

Nejprve PASSING klauzule je místo, kde specifikujeme data XML, která chceme zpracovat. V tomto případě data pocházejí z hotelů ve sloupci hoteldata stůl. Říkáme tomu výraz dokumentu .

Těsně před PASSING klauzule vidíte výraz XPath '/hotels/hotel/rooms/room' . Říkáme tomu výraz generující řádek nebo jen řádkový výraz .

Máme SLOUPCE klauzule další, deklarující několik sloupců. Pro každý sloupec uvádíme typ dat a také volitelnou PATH klauzuli, kterou nazýváme sloupcový výraz .

XMLTABLE Operační teorie spočívá v tom, že řádkový výraz se aplikuje na výraz dokumentu a rozdělí dokument na kousky, aby se vygenerovaly řádky; pro každý takto vygenerovaný řádek jsou použity různé sloupcové výrazy k získání hodnot pro každý sloupec.

Sloupcový výraz je výraz XPath, který získává hodnotu začínající z XML pro aktuální řádek. Pokud není PATH je zadán, pak se jako výraz XPath použije samotný název sloupce. Všimněte si, že ve sloupci název_hotelu použili jsme cestu s „../ “, což znamená „jít nahoru“ v dokumentu XML a získat hodnoty z objektů „kontejner“ v dokumentu. Můžeme také použít xml PATH '.' v řádku, což nám poskytuje úplný zdrojový kód XML pro daný řádek.

Jeden sloupec může být označen jako PRO ORDINALITA . Sloupec je pak typu INTEGER a je očíslován postupně pro každý řádek získaný z dokumentu. (Pokud existuje více vstupních dokumentů, například když máte v tabulce více řádků, počítadlo začíná od 1 pro každý nový dokument.

K dispozici je také VÝCHOZÍ doložka. Pokud XPath pro sloupec neodpovídá hodnotě pro určitý řádek, pak DEFAULT je použita hodnota.

Některé z těchto sloupců byly označeny jako NOT NULL . Pokud neexistuje žádná shoda a žádné DEFAULT je specifikována klauzule (nebo DEFAULT také vyhodnotí jako NULL ), dojde k chybě.

Nebudu se podrobněji zabývat XPath, což je mocný jazyk, ale jako užitečné zdroje mohu nabídnout článek o XPath na Wikipedii a dokument s oficiálním doporučením od W3C.

Úplná syntaxe XMLTABLE

Dokumentovaná synopse syntaxe je:

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

Všimněte si, že výraz dokumentu může být odkazem na nějakou tabulku, kterou máte v klauzuli FROM, nebo to může být úplný dokument XML jako řetězcový literál. Klauzule BY REF nemají žádný účinek; jsou zde kvůli kompatibilitě se standardem as jinými databázovými systémy.

Nepokryl jsem XMLNAMESPACES klauzule v tomto příspěvku; To nechávám na budoucí splátku.

Použití SQL nahoře

Jak již bylo zmíněno, jakmile XMLTABLE zpracuje data do relační formy, můžete pomocí známých nástrojů dělat, co chcete. Pokud jste například měli jiný dokument XML s více zaměstnanci v každém hotelu,

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

Je snadné získat celkové platy pro každou měnu, kterou musíte zaplatit v každém hotelu,

  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 měna součet
Valparaíso CLP 1200000
Valparaíso EUR 80 000
La Mancha PTA 80 000

Závěr

V tomto článku jsem se zabýval novou funkcí XMLTABLE se objeví v PostgreSQL verze 10. Myslím, že XMLTABLE je skvělá funkce pro integraci externích dat a doufám, že i pro vás bude cenná. Prosím otestujte a nahlaste případné problémy, abychom je mohli vyřešit před konečným vydáním. Pokud máte rádi XMLTABLE , nezapomeňte nám dát vědět zanecháním komentáře!


  1. Vánoce přicházejí brzy (Oracle 12.2)

  2. Musím se chránit před vkládáním SQL, pokud jsem použil rozevírací seznam?

  3. SQL:Získejte záznamy vytvořené v časovém rozsahu pro konkrétní data

  4. Porovnání MySQL s hodnotou null