Saya baru saja melakukan patch oleh Pavel Stěhule yang menambahkan XMLTABLE fungsionalitas ke PostgreSQL 10. XMLTABLE adalah fitur yang sangat berguna yang ditentukan oleh standar SQL/XML, yang memungkinkan Anda mengubah data XML menjadi bentuk relasional, sehingga Anda dapat menggabungkannya dengan data relasional lainnya. Fitur ini memiliki banyak kegunaan; terus membaca untuk beberapa detail tentangnya.
Mungkin kasus penggunaan yang paling menarik dari XMLTABLE adalah mengekstrak data dari beberapa dokumen XML untuk dimasukkan ke dalam tabel relasional, selama pemrosesan ETL dalam basis data. Namun, XMLTABLE dapat digunakan on-the-fly pada data yang disimpan dalam kolom XML, sehingga setelah data dalam bentuk relasional, Anda dapat menerapkan operasi standar apa pun yang Anda inginkan, seperti menambahkan WHERE klausa, melakukan agregasi, bergabung ke tabel lain, dan sebagainya.
Contoh Sederhana
Sebagai contoh, anggaplah Anda mengelola jaringan hotel, dan data disimpan dengan cara ini:
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;
Dengan XMLTABLE , Anda dapat mengubahnya menjadi tabel berformat relasional yang terdiri dari jumlah dan kapasitas kamar, yang memberikan anotasi untuk setiap hotel di jaringan Anda:
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 | nama_hotel | room_id | kapasitas | komentar |
---|---|---|---|---|
1 | La Mancha | 201 | 3 | Tampilan Kanal yang bagus |
2 | La Mancha | 202 | 5 | Ruang biasa |
3 | Valparaíso | 201 | 2 | Sangat bising |
4 | Valparaíso | 202 | 2 | Ruang biasa |
Menjelaskan sintaks
Mari pelajari kueri di atas. XMLTABLE klausa harus berada di FROM bagian dari kueri. Kami juga memiliki hoteldata dalam DARI , yang memasukkan data ke XMLTABLE .
Pertama, LULUS klausa adalah tempat kita menentukan data XML yang ingin kita proses. Dalam hal ini, data berasal dari hotel kolom di hoteldata meja. Kami menyebutnya ekspresi dokumen .
Tepat sebelum LULUS klausa Anda melihat ekspresi XPath '/hotels/hotel/rooms/room' . Kami menyebutnya ekspresi yang menghasilkan baris atau hanya ekspresi baris .
Kami memiliki KOLOM klausa berikutnya, mendeklarasikan beberapa kolom. Untuk setiap kolom kami menunjukkan tipe data serta opsional PATH klausa, yang kita sebut ekspresi kolom .
XMLTABLE teori operasi adalah bahwa ekspresi baris diterapkan ke ekspresi dokumen, mengiris dokumen menjadi beberapa bagian untuk menghasilkan baris; untuk setiap baris yang dihasilkan, berbagai ekspresi kolom diterapkan untuk mendapatkan nilai untuk setiap kolom.
Ekspresi kolom adalah ekspresi XPath yang memperoleh nilai mulai dari XML untuk baris saat ini. Jika tidak ada PATH ditentukan, maka nama kolom itu sendiri digunakan sebagai ekspresi XPath. Perhatikan bahwa di kolom hotel_name kami menggunakan jalur yang memiliki “../ “, yang berarti “naik” dalam dokumen XML untuk mengambil nilai dari objek “wadah” dalam dokumen. Kami juga dapat menggunakan xml PATH '.' berturut-turut, yang memberi kita XML sumber lengkap untuk baris itu.
Satu kolom dapat ditandai UNTUK ORDINALITAS . Kolom tersebut kemudian bertipe INTEGER , dan diberi nomor secara berurutan untuk setiap baris yang diperoleh dari dokumen. (Jika ada beberapa dokumen input, seperti ketika Anda memiliki beberapa baris dalam sebuah tabel, penghitung dimulai dari 1 untuk setiap dokumen baru).
Ada juga DEFAULT ayat. Jika XPath untuk kolom tidak cocok dengan nilai untuk baris tertentu, maka DEFAULT nilai yang digunakan.
Beberapa kolom ini telah ditandai sebagai NOT NULL . Jika tidak ada kecocokan, dan tidak ada DEFAULT klausa ditentukan (atau DEFAULT juga mengevaluasi ke NULL ), terjadi kesalahan.
Saya tidak akan membahas lebih detail tentang XPath, yang merupakan bahasa yang kuat, tetapi saya dapat menawarkan artikel XPath di Wikipedia, dan dokumen rekomendasi resmi dari W3C sebagai sumber yang berguna.
Sintaks XMLTABLE lengkap
Synopsis sintaks yang didokumentasikan adalah:
xmltable
( [XMLNAMESPACES(namespace uri
ASnamespace name
[, ...])]row_expression
PASSING [BY REF]document_expression
[BY REF] COLUMNSname
{type
[PATHcolumn_expression
] [DEFAULTexpr
] [NOT NULL | NULL] | FOR ORDINALITY } [, ...] )
Perhatikan bahwa ekspresi dokumen dapat menjadi referensi ke beberapa tabel yang Anda miliki dalam klausa FROM, atau dapat berupa dokumen XML lengkap sebagai literal string. Klausa BY REF tidak memiliki efek apa pun; mereka ada untuk kompatibilitas dengan standar dan dengan sistem database lainnya.
Saya belum membahas XMLNAMESPACES klausa dalam posting ini; Saya akan meninggalkannya untuk cicilan di masa mendatang.
Menerapkan SQL di atas
Seperti yang disebutkan, setelah XMLTABLE memproses data ke dalam bentuk relasional, Anda dapat melakukan apa pun yang Anda inginkan menggunakan alat yang terkenal. Misalnya, jika Anda memiliki dokumen XML lain dengan lebih banyak personel di setiap 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>$$);
Sangat mudah untuk mendapatkan gaji total untuk setiap mata uang yang harus Anda bayar di setiap 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 | mata uang | jumlah |
---|---|---|
Valparaíso | CLP | 1200000 |
Valparaíso | EUR | 80000 |
La Mancha | PTA | 80000 |
Kesimpulan
Dalam artikel ini, saya telah membahas fitur baru XMLTABLE untuk muncul di PostgreSQL versi 10. Saya rasa XMLTABLE adalah fitur hebat untuk mengintegrasikan data eksternal, dan saya harap Anda juga menganggapnya berharga. Silakan uji dan laporkan masalah apa pun, sehingga kami dapat menyelesaikannya sebelum rilis final. Jika Anda suka XMLTABLE , pastikan untuk memberi tahu kami dengan meninggalkan komentar!