Schlangenbeschwörer

Als Chief-Architect, der etwas auf sich hält, muss man natürlich immer die neuesten Technologien kennen und sei es auch nur um andere Architects oder Frickler mit seinem enormen Fachwissen und Buzzwords zu beeindrucken.

Im Zuge dessen habe ich mir vor einigen Tagen mal die öffentliche, kostenlose Beta von IBMs DB2 Version 9.1 (Viper) angeschaut. Killer-Feature dieser Version ist die Synergie (ich mag dieses Wort) von relationalen Datenbanken und XML. Dazu wurde ein neuer Attributtyp namens XML eingefügt, der XML-Daten hirarchisch (also nicht einfach als CLOB oder varchar) speichert. Anfragen an dieses Attribut kann man über XQUERY (von einigen wenigen Eingeweihten ausgesprochen als [ixquiehri]) und XPATH formulieren.

Schauen wir uns das im Folgenden also mal genauer an (Während der Splash-Screen der Steuerungszentrale läuft, kann man sogar noch einen Kaffee trinken. IBM denkt eben an alles. Enterprise-Software halt.)… (Read more klicken)

Die folgenden Codebeispiele setzen die Installation der Sample-DB vorraus, die von IBM mitgeliefert wird

Die Spalte Info der Tabelle Customer ist ein XML-Attribut. Das folgende SQL-Kommando gibt uns einen Einblick in den Inhalt.
XQUERY db2-fn:xmlcolumn('CUSTOMER.INFO')

Resultat:
Kathy Smith5 RosewoodToronto Ontario M6W-1E6 416-555-1358
Kathy Smith25 EastCreekToronto Ontario M8X-3T6 416-555-1358
Jim Noodle25 EastCreekMarkham Ontario N9C-3T6 905-555-7258
Robert Shoemaker1596 BaselineAurora Ontario N8X-7F8 905-555-7258 416-555-2937 905-555-8743 613-555-3278
Matt Foreman1596 BaselineToronto Ontario M3Z-5H9 905-555-4789 416-555-3376Gopher Runner 416-555-3426

Dies ist die Komplette Struktur des XML-Inhaltes dieses Attributs. Zu beachten ist lediglich, dass das gesamte Dokument implizit von den Tags und umschlossen ist. Es ist also well-formed.

Benötigen wir nun nur den Namen des ersten Kunden als Plain-Text so hilft uns der Befehl
XQUERY db2-fn:xmlcolumn('CUSTOMER.INFO')[1]/customerinfo/name/text();
Resultat:
Kathy Smith
Wollten wir den Namen inklusive des Tags, so genügt es den Funktionsaufruf text() am Ende des Befehls wegzulassen.

Nun wollen wir die Ausgabe der Strassen aller Leute, die in Toronto wohnen. Wir erledigen dieses Query mit Hilfe eines FLWOR-Ausdrucks:
XQUERY {
for $customer in db2-fn:xmlcolumn('CUSTOMER.INFO')/customerinfo
let $city:=$customer/addr/city, $street:=$customer/addr/street/text()
where $city="Toronto"
return {$street} }

Resultat:
5 Rosewood25 EastCreek1596 Baseline

Und nun bringen wir mal XML und SQL zusammen. Wir wollen KundenID, Name und Strasse aller Kunden, die in Toronto wohnen. Dazu joinen wir über normale relationale Daten und XML-Daten:
SELECT sqltable.Cid, xmltable.name, xmltable.strasse
FROM Customer sqltable,
xmltable('$customerinfo/customerinfo' passing sqltable.INFO as "customerinfo"
columns name varchar(100) path 'name',
wohnort varchar(100) path 'addr/city',
strasse varchar(100) path 'addr/street') xmltable
WHERE xmltable.wohnort='Toronto';

Resultat:
db2 tabelle

Diese kleinen Beispiele sollen nur einen kurzen Einblick geben in das, was prinzipiell möglich ist. Wer sich näher dafür interessiert, dem seinen folgende 2 Links empfohlen:
IBM: Query DB2 XML data with XQuery
IBM: Query DB2 XML data with SQL

Nachtrag 14.12.2006: Der Wordpress-Editor hat mal wieder alle XML-Tags gefressen. Eventuell trag ich die später nochmals nach.


( ! ) Fatal error: Maximum execution time of 30 seconds exceeded in /home/philip/www/blog_philippreissing_com/wp-content/plugins/intensedebate/class.json.php on line 265
Call Stack
#TimeMemoryFunctionLocation
10.502015219592shutdown_action_hook( )../wp-settings.php:0
20.502015219592do_action( )../wp-settings.php:585
30.502215219592call_user_func_array ( )../plugin.php:339
40.502215219592id_ping_queue( )../plugin.php:0
50.614527348264id_queue->ping( )../intensedebate.php:347
60.614527348264id_queue->send( )../intensedebate.php:824
70.614927349784Services_JSON->encode( )../intensedebate.php:837
80.616627413380array_map ( )../class.json.php:394
930.046930940516Services_JSON->encode( )../class.json.php:0
1030.046930940516array_map ( )../class.json.php:409
1130.048330940516Services_JSON->name_value( )../class.json.php:0
1230.048330940516Services_JSON->encode( )../class.json.php:437
1330.048430940516array_map ( )../class.json.php:382
1430.051330940516Services_JSON->name_value( )../class.json.php:0
1530.051330940516Services_JSON->encode( )../class.json.php:437