DB2 wird hybrid mit neuartiger XML-Unterstützung

Abfrage mit XQuery und SQL

XQuery hat sich als akzeptierte Sprache zur Abfrage und Verarbeitung von XML-Daten etabliert. Als funktionale Sprache implementiert XQuery neben den auf XPath basierenden Navigationsmechanismen über XML eine Reihe von arithmetischen Operatoren, Vergleichsoperatoren, konditionalen Ausdrücken und vieles mehr. Dabei übernimmt XQuery das im XML Schema definierte Typsystem und operiert über einem eigenen Datenmodel, was vom W3C definiert wird.

Genau dieses Datenmodel wird in DB2 9 mit pureXML verwaltet und ermöglicht, dass XQuery-Anfragen direkt über dem gespeicherten Format der XML-Daten ausgeführt werden können. Kein zusätzliches Parsen oder andere Datentransformationen sind beim Zugriff mit pureXML notwendig.

Wie kann man nun mit XQuery die in DB2 gespeicherten Daten verarbeiten? Für den Zugriff auf Datenbanken überlässt der kommende Standard den Herstellern eine geeignete Implementierung einer Input-Funktion. Somit bietet DB2 9 zwei eigene XQuery-Inputfunktionen an, mit denen die zu verarbeitenden XML-Daten identifiziert werden:

  • db2-fn:sqlquery()
  • db2-fn:xmlcolumn()

Der Parameter für die db2-fn:xmlcolumn()-Inputfunktion ist Schemaname.Tabellename.Spaltenname. Die Spalte muss dabei vom Datentyp XML sein. Mit db2-fn:xmlcolumn() wird auf alle XML-Dokumente, die in dieser Spalte gespeichert sind, zugegriffen.

Zum Beispiel werden mit folgender XQuery-Anfrage alle Namenselemente der Produktdaten ausgegeben.

XQuery db2-fn:xmlcolumn('PRODUKT.BESCHREIBUNG')//Name

Zu beachten ist der Präfix „XQuery“, der jedem XQuery-Ausdruck vorangestellt werden muss. Damit teilt man DB2 mit, dass der XQuery Parser und nicht der SQL Parser zur Bearbeitung der Anfrage verwendet werden soll.

Fragt man die Beispieldatenbank mit obiger XQuery-Anfrage ab, findet DB2 allerdings keine Resultate, obwohl zuvor unsere fünf Produktdaten in die Produkttabelle importiert wurden. Ein Blick auf die Beispieldokumente verrät den Grund – die Elemente sind einem eigenen Namensraum (http://www.beipiel.de/demoProdukt) zugeordnet, der auch im XQuery-Kontext definiert werden muss. Dies wird entweder mit der Anweisung ’declare default element namespace “<<URI>>” ; bzw. der ’declare element namespace localName:“<<URI>>”;’ erreicht.

Unter Berücksichtigung des Namensraums iteriert der folgende XQuery-Ausdruck über alle Produktdaten in Produkt.Beschreibung und gibt den Namen der Produkte in einem neu konstruierten Element ProduktName aus:

XQuery declare default element namespace "http://www.beispiel.de/demoProdukt";
    for $prod in db2-fn:xmlcolumn('PRODUKT.BESCHREIBUNG')//Name/text()
    return  {$prod} 

Die zweite Inputfunktion, db2-fn:sqlquery(), erlaubt einen selektiveren Zugriff auf XML-Dokumente, indem ein gewöhnlicher SELECT-Ausdruck als Parameter akzeptiert wird. So lassen sich gezielt XML-Dokumente über eine geeignete WHERE-Klausel bearbeiten:

XQuery declare default element namespace "http://www.beispiel.de/demoProdukt";
       for $prod in db2-fn:sqlquery('SELECT BESCHREIBUNG FROM PRODUKT 
                                     WHERE pid>5')//Name/text()
       return  {$prod} 

Genau wie vorheriges Beispiel zu db2-fn:xmlcolumn() gibt auch obige XQuery-Anfrage die Namenselemente der Produktdaten aus. Einziger Unterschied ist die Beschränkung der Ausgabe auf Produkte mit dem Identifier (pid) größer 5.

Es lassen sich beliebig komplexe XQuery-Anfragen gemäß des kommenden W3C-Standards in DB2 realisieren. Dies ermöglicht die Abarbeitung komplexerer Applikationslogik auf dem Datenserver anstatt auf der Applikationsebene. Somit können XML-relevante Programmteile direkt auf den nativ gespeicherten XML-Daten in der Datenbank ausgeführt werden. Ein Auslesen und womöglich nochmaliges Parsen von XML in der Applikationsebene wird dadurch vermieden. Die von der Applikation benötigten Informationen werden direkt in vorverarbeiteter Form von der Datenbank zurückgegeben.

Wie erwähnt, steht neben XQuery auch SQL zur Abfrage von XML zur Verfügung. So kann mit einem SELECT-Ausdruck das gesamte XML-Dokument ausgegeben werden. Nachfolgender Befehl gibt alle XML-Produktdaten aus:

SELECT Beschreibung FROM Produkt

Implizit wird dabei das nativ gespeicherte XML-Dokument serialisiert und ausgegeben. Oftmals möchte man nicht das gesamte XML-Dokument auslesen, sondern ist an einzelnen Element- oder Attributinhalten innerhalb der Dokumentenstruktur interessiert. Diese sollen, wie andere Spaltenwerte auch, in die Ausgabemenge projiziert werden. SQL selbst bietet dafür keine geeigneten Sprachmittel – es kann immer jeweils nur das gesamte Dokument gelesen werden.Wie bereits gesehen, ist XQuery für diese Aufgabe genau das richtige Werkzeug. Aber wie lässt sich XQuery mit SQL kombinieren und innerhalb eines SELECT-Ausdrucks verwenden? Abhilfe schaffen neue SQL/XML:2006-Funktionen.

Neben den bekannten SQL/XML-Publishing-Funktionen, die bereits seit DB2 Version 7 zum Erzeugen von XML-Dokumenten auf Basis relationaler Daten unterstützt werden, implementiert DB2 9 weitere SQL/XML-Funktionen, die im ANSI-Standard definiert sind. Tabelle 1 gibt eine Übersicht über die wichtigsten neuen Funktionen und ein kurzes Beispiel zu deren Verwendung.

Tabelle 1: Übersicht über die wichtigsten neuen Funktionen
Funktion Beschreibung Beispiel
XMLVALIDATE Validiert einen XML-Wert gegen ein registriertes XML Schema und annotiert den XML-Wert entsprechend mit Typinformationen.
INSERT INTO Produkt(Beschreibung) VALUES(
   XMLVALIDATE ('...'
   ACCORDING TO ID 'TEST.PRODUKT'))
XMLEXISTS Funktioniert wie ein Prädikat und bestimmt, ob ein XQuery-Ausdruck ein Ergebnis liefert oder nicht (Boolesche Funktion).
SELECT ID FROM T1 
WHERE 
   XMLEXSISTS ('$d//Preis[@Währung=EUR"]' 
       PASSING Beschreibung AS "d")
XMLQUERY Führt ein XQuery-Ausdruck aus und liefert das Ergebnis.
SELECT ID, 
  XMLQUERY('for $i in $d/Produkt
	     let $j := $i//Name
             return $j' 
           PASSING Beschreibung AS "d") 
FROM T1
XMLTABLE Führt ein XQuery-Ausdruck aus und liefert das Ergebnis als Tabelle.
Siehe Absatz "XML tabellarisch
darstellen mit XMLTABLE()"
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.