Току-що поставих пач от Павел Стюле, който добавя XMLTABLE функционалност към PostgreSQL 10. XMLTABLE е много полезна функция, продиктувана от стандарта SQL/XML, която ви позволява да превърнете вашите XML данни в релационна форма, за да можете да ги смесвате с останалите си релационни данни. Тази функция има много приложения; продължете да четете за някои подробности за него.
Вероятно най-интересният случай на използване на XMLTABLE е да се извлекат данни от някакъв XML документ за вмъкване в релационна таблица по време на ETL обработка в базата данни. Въпреки това XMLTABLE може да се използва в движение върху данни, съхранявани в XML колони, така че след като данните са в релационна форма, можете да приложите всякакви стандартни операции, които искате, като например добавяне на WHERE клаузи, извършване на агрегиране, присъединяване към други таблици и т.н.
Прост пример
Като пример, да предположим, че администрирате хотелска верига и че данните се съхраняват по следния начин:
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;
С XMLTABLE , можете да превърнете това в релативно форматирана таблица, състояща се от номера на стаи и капацитет, с пояснения за всеки хотел във вашата верига:
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 | име на хотел | room_id | капацитет | коментар |
---|---|---|---|---|
1 | Ла Манча | 201 | 3 | Страхотен изглед към канала |
2 | Ла Манча | 202 | 5 | Обикновена стая |
3 | Валпараисо | 201 | 2 | Много шумен |
4 | Валпараисо | 202 | 2 | Обикновена стая |
Обяснение на синтаксиса
Нека проучим заявката по-горе. XMLTABLE клаузата трябва да влезе в FROM част от заявката. Имаме и хотелски данни в ОТ , което подава данните в XMLTABLE .
Първо, ПРАВЯНЕ клаузата е мястото, където указваме XML данните, които искаме да обработим. В този случай данните идват от хотелите колона в данните за хотела маса. Наричаме това изразът на документа .
Точно преди МИНАВАНЕ клауза виждате XPath израз '/hotels/hotel/rooms/room' . Ние наричаме това израз, генериращ ред или просто изразът на реда .
Имаме КОЛОНИ клауза следваща, декларираща няколко колони. За всяка колона посочваме тип данни, както и незадължителен PATH клауза, която наричаме израз на колона .
XMLTABLE Теорията на работа на „е“ е, че изразът на реда се прилага към израза на документа, като се нарязва документът на парчета, за да се генерират редове; за всеки генериран по този начин ред се прилагат различните изрази на колона, за да се получат стойностите за всяка колона.
Изразът на колоната е израз XPath, който получава стойност, започваща от XML за текущия ред. Ако няма PATH е посочено, тогава самото име на колона се използва като XPath израз. Имайте предвид, че в колоната име_хотел използвахме път с „../ “, което означава „да се качите нагоре“ в XML документа, за да вземете стойности от обектите „контейнер“ в документа. Можем също да използваме xml PATH '.' в ред, което ни дава пълния изходен XML за този ред.
Една колона може да бъде маркирана ЗА РЕДНОСТ . Тогава колоната е от тип INTEGER , и се номерира последователно за всеки ред, получен от документа. (Ако има множество входни документи, например когато имате няколко реда в таблица, броячът започва от 1 за всеки нов документ).
Има и ПО ПОДРАЗБИРАНЕ клауза. Ако XPath за колона не съвпада със стойност за определен ред, тогава DEFAULT се използва стойност.
Някои от тези колони са маркирани като NOT NULL . Ако няма съвпадение и няма DEFAULT е посочена клауза (или DEFAULT също се оценява на NULL ), възниква грешка.
Няма да навлизам в повече подробности за XPath, който е мощен език, но мога да предложа статията на XPath в Wikipedia и официалния препоръчителен документ от W3C като полезни ресурси.
Пълният синтаксис на XMLTABLE
Документираният синопсис на синтаксиса е:
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 } [, ...] )
Имайте предвид, че изразът на документа може да бъде препратка към някаква таблица, която имате в клаузата FROM, или може да бъде пълен XML документ като низов литерал. Клаузите BY REF нямат никакъв ефект; те са там за съвместимост със стандарта и с други системи за бази данни.
Не съм покрил XMLNAMESPACES клауза в тази публикация; Оставям го за бъдеща вноска.
Прилагане на SQL отгоре
Както споменахме, след като XMLTABLE обработи данните в релационна форма, можете да правите каквото искате, като използвате добре познати инструменти. Например, ако имате друг XML документ с повече персонал във всеки хотел,
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>$$);
Лесно е да получите общите заплати за всяка валута, която трябва да плащате във всеки хотел,
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;
хотел | валута | сума |
---|---|---|
Валпараисо | CLP | 1200000 |
Валпараисо | EUR | 80 000 |
Ла Манча | PTA | 80 000 |
Заключение
В тази статия разгледах новата функция XMLTABLE да се появи в PostgreSQL версия 10. Мисля, че XMLTABLE е страхотна функция за интегриране на външни данни и се надявам и вие да го намерите за ценно. Моля, тествайте го и докладвайте за всички проблеми, за да можем да ги разрешим преди окончателното издание. Ако харесвате XMLTABLE , не забравяйте да ни уведомите, като оставите коментар!