Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  1/2006
suche: 
Dieser Artikel richtet sich an Datenbankentwickler und Software-Architekten.

Glossar

CLOB
CLOB (Character Large Object) ist der (Oracle) Datentyp für ein Datenbankfeld zur Speicherung von großen Textdaten (bis zu 4 GB).
DTD
Die Dokumenttypdefinition (englisch: "Document Type Definition") ist eine Deklaration in SGML- und XML-Dokumenten, die die Struktur eines solchen Dokuments festlegt.
Parser
Programme oder Programmteile, die XML-Daten auslesen, interpretieren und gegebenenfalls auf Gültigkeit prüfen.
Oracle Text
Oracle Text ist ein Bestandteil von Oracle 9i und 10g. Oracle Text bietet umfassende Möglichkeiten der Textverarbeitung. So z. B. Suche (Volltext-, Kontext-, Ranking usw.), Filterung, Klassifikation usw. Oracle Text unterstützt verschiedene Datenformate (HTML, XML, PDF usw.)
XML
Die Extensible Markup Language (XML) ist ein Standard zur Erstellung maschinen- und menschenlesbarer Dokumente in Form einer Baumstruktur.
XML Type
Ab Oracle 9i steht XMLTyp als neuer Datentyp zur Verfügung. Durch diesen Datentyp werden SQL-Operationen auf XML-Inhalte genauso ermöglicht wie XML-Operationen auf SQL-Inhalte. Oracle stellt spezielle Funktionen zum Erzeugen, Extrahieren und Indizieren von XML-Daten, welche in XMLType-Strukturen liegen, zur Verfügung.

Oracle und XML (Teil I):
Ein besonderer Cocktail

Relationale Datenbanken sind unumstritten im Einsatz, wenn es um die Verwaltung großer Datenmengen geht. XML hat sich als Format für den Datenaustausch zwischen Anwendungen etabliert. Oracle hat die Bedeutung von XML erkannt und bietet deshalb eine eigene XML-Schnittstelle an.

XML-Dokumente können in Oracle auf verschiedene Arten gespeichert werden:

  1. Die einfachste Methode: Das XML-Dokument wird als Dokument in eine CLOB-Spalte übernommen.
  2. Die zweite Methode, bei der Oracle das XML-Dokument analysiert und die Daten in Tabellen ablegt, erläutern wir in den Abschnitten "Parsen von XML-Dokumenten" und "XML SQL Utility".
  3. Die dritte Methode, bei der Oracle das XML-Dokument als XMLType ablegt, werden wir in Teil II genauer betrachten.

Im Gegenzug zum Speichern können Daten aus Datenbanktabellen, die mittels SQL-Abfrage ermittelt wurden, auch wieder in XML-Dokumente umgewandelt werden. Abbildung 1 gibt einen Überblick über alle Komponenten, die in den beiden Teilen dieses Artikels vorgestellt werden.

Speichern in CLOB-Feldern

Die einfachste Methode, XML-Dokumente in einer Datenbank zu halten, sind CLOB-Felder. Wenn man XML-Daten in einem CLOB-Feld abspeichert, bedeutet dies, dass sie genau so abgelegt werden, wie sie geliefert werden. Daher kann beim Wiederherstellen des Dokuments kein Daten- oder Informationsverlust entstehen.

Diese Speichermethode ist immer dann von Vorteil, wenn die Struktur der XML-Daten veränderlich ist, weil eine aufwändige Migration der Datenbankobjekte entfallen kann. Allerdings hat die Speicherung von XML-Daten in CLOB-Feldern auch Nachteile. So ist die Unterstützung der Datenbank bei der echten Verarbeitung dieser Dokumente nur sehr begrenzt. Außerdem muss bei einem Update immer das komplette Dokument ersetzt werden, was nicht unbedingt der performanteste Weg ist. Auch die begrenzte Möglichkeit einer effizienten Indizierung ist hier zu nennen. Sie ist in diesem Fall nur über Oracle-Text möglich.

Fehlerbeseitigung
Abb. 1: Überblick über sämtliche Komponenten, die in diesem Artikel vorgestellt werden.

XML generieren: Das Paket DBMS_XMLGEN

Mit dem Paket DBMS_XMLGEN, welches in Oracle in der Standardinstallation zur Verfügung steht, lassen sich XML-Dokumente aus einer SQL-Abfrage generieren und ausgeben, aber auch in einem CLOB-Feld abspeichern.

In Abbildung 2 ist die Prozedur xml_to_clob dargestellt, mit deren Hilfe wir aus den Daten einer Tabelle auto ein XML-Dokument erstellen möchten. Die Tabelle auto soll Autonamen enthalten. Dazu legen wir die Tabelle mit zwei Spalten an. Zum einen die Spalte AUTO_ID (NUMBER), die eine eindeutige ID enthält und zum anderen die Spalte AUTO_NAME (VARCHAR2), die den Markennamen des Autos enthält.

CREATE OR REPLACE PROCEDURE xml_to_clob
IS
    -- Anlegen der Variable, für den Context-Handle
    qryCtx DBMS_XMLGEN.ctxHandle;
    -- Anlegen der Variable erg vom Typ CLOB. Diese
    -- Variable soll das Ergebnis abspeichern
    erg CLOB;
BEGIN
    -- Kontext mit der Abfrage, aus der das XML
    -- generiert werden soll, erzeugen
    qryCtx := dbms_xmlgen.newContext
    ('SELECT * FROM auto');
    -- ROW durch 'Auto' ersetzen:
    dbms_xmlgen.setRowTag(qryCtx,'Auto');
    -- ROWSET durch 'Autoliste' ersetzen:
    dbms_xmlgen.setRowSetTag(qryCtx,'Autoliste');
    erg := dbms_xmlgen.getXML(qryCtx);
    -- das generierte XML-Dokument in der
    -- Tabelle temp_clob speichern.
    INSERT INTO temp_clob VALUES (erg);
    -- Context schließen
    dbms_xmlgen.closeContext(qryCtx);
END;
/
Abb. 2: Generieren von XML aus einer SQL-Abfrage mit DBMS_XMLGEN.

Um das XML-Dokument zu generieren, verwenden wir Funktionen, die das Paket DBMS_XMLGEN zur Verfügung stellt:

In unserem Beispiel verwenden wir all diese Funktionen. Zunächst setzen wir den Kontext, welchem die Datenbankabfrage select * from auto übergeben wird. Diese Abfrage selektiert die Daten, die wir zum Erzeugen unseres XML-Dokuments verwenden wollen, aus der Datenbank.

Anschließend definieren wir die Tags für jede Ergebniszeile mit der Funktion setRowTag und das Root-Element mit der Funktion setRowSetTag.

Anschließend rufen wir die Funktion getXML auf und speichern das Ergebnis in der Variablen erg. Den Inhalt dieser Variablen speichern wir nun in die Tabelle temp_clob (temp_clob besteht aus einem Feld vom Typ CLOB).

Dieses ist nötig, da wir einen CLOB in unserer Prozedur nicht ohne weiteres ausgeben können. Daher speichern wir das Ergebnis zunächst in der Tabelle ab und selektieren es dann wieder aus der Datenbank.

Durch das Selektieren bekommen wir das in Abbildung 3 dargestellte Ergebnis ausgegeben. Wir bekommen ein XML-Dokument, welches, wie durch die Funktion setRowSetTag definiert, Autoliste als Root-Element enthält.

<?xml version="1.0" ?>
<Autoliste>
    <Auto>
      <AUTO_ID>1</AUTO_ID>
      <AUTO_NAME>Alfa Romeo 156</AUTO_NAME>
    </Auto>
    <Auto>
      <AUTO_ID>2</AUTO_ID>
      <AUTO_NAME>Alfa Romeo 147</AUTO_NAME>
    </Auto>
</Autoliste>
Abb. 3: Ergebnis einer Abfrage mit DBMS_XMLGEN.

Jede Ergebniszeile wird, wie durch die Funktion setRowTag definiert, durch das Tag <Auto> dargestellt. Innerhalb der Ergebniszeile werden die eigentlichen Daten dargestellt. Diese Tags sind genauso benannt wie die Spalten der Tabelle, nämlich AUTO_NAME und AUTO_ID.

Parsen von XML-Dokumenten

Mit den PL/SQL-Packages XMLParser und XMLDOM stellt Oracle Funktionen zum Parsen und Transformieren von XML-Dokumenten in der Datenbank zur Verfügung. Mit dem Paket XMLParser wird das Dokument analysiert und der DOM-Baum aufgebaut, der im Hauptspeicher zur Verfügung steht.

Das Dokument wird vom Parser geparst, wodurch sicher gestellt werden kann, dass das Dokument "wohlgeformt" (wellformed) ist. Wenn eine DTD vorliegt und die entsprechende Funktionalität des Parsers vom Entwickler eingeschaltet ist, wird gegen diese auch noch validiert.

Oracle stellt Parser für PL/SQL, Java, C++ und C zur Verfügung. Nun wollen wir uns die Funktionalität des Parsens eines XML-Dokumentes innerhalb der Datenbank genauer ansehen (siehe Abbildung 4).

CREATE OR REPLACE FUNCTION parse_XMLDoc
   (xmldoc       IN CLOB,
   wellformed    OUT BOOLEAN)
RETURN xmlDom.DOMDocument IS
   v_xmlDoc      xmlDom.DOMDocument;
   v_parser      xmlparser.Parser;
   parserError   EXCEPTION;
   PRAGMA EXCEPTION_INIT (parserError, -20100);
BEGIN
   v_parser := xmlparser.newParser;
   xmlparser.ParseClob(v_parser,xmldoc);
   v_xmlDoc := xmlparser.getDocument(v_parser);
   xmlparser.freeParser(v_parser);
   wellformed := TRUE;
   RETURN v_xmlDoc;
EXCEPTION
   WHEN parserError THEN
     xmlparser.FreeParser(v_parser);
     wellformed := FALSE;
END;
Abb. 4: Parsen eines XML-Dokumentes innerhalb der Datenbank.

Wir legen die Prozedur parse_XMLDoc an, die ein XML-Dokument parsen soll, welches ihr als CLOB übergeben wird. Die Prozedur gibt das geparste DOM-Dokument zurück. Zusätzlich wird ein Boolean zurückgeliefert, der aussagt, ob die Datei wohlgeformt ist oder nicht.

Zunächst werden die lokalen Variablen deklariert, die wir benötigen. Variable v_xmlDoc soll den Rückgabewert der Prozedur aufnehmen und v_parser ist für die Parser-Instanz vorgesehen.

Um Fehler, die beim Parsen auftreten können, abzufangen, wird die Exception parserError definiert und auf die Fehlernummer -20100 abgebildet. Innerhalb der Prozedur erzeugen wir mit der Funktion newParser eine neue Parser- Instanz.

Zunächst parsen wir das XML-Dokument, welches der Prozedur übergeben wurde, mit der Funktion parseCLOB, der als Parameter die Parser-Instanz und das XML-Dokument übergeben werden. Anschließend wird die Parser- Instanz wieder freigegeben. Ist innerhalb dieses Vorgangs keine Exception aufgetreten, ist das Parsen fehlerfrei durchgelaufen und das Dokument somit wohlgeformt.

Also setzen wir unseren Rückgabeparameter auf true. Falls ein parserError auftritt wird dieser im Exception-Block abgefangen und zunächst die Parser-Instanz wieder freigegeben. Anschließend setzen wir den Rückgabeparameter auf false.

XML SQL Utility (XSU)

Die XML SQL Utility (XSU) stellt seit Oracle 8i eine Möglichkeit dar, XML-Daten mit Oracle zu verwalten bzw. XML-Daten aus der Oracle-Datenbank zu generieren. Dabei kann XSU mit Daten aus Tabellen oder Views XML-Dokumente generieren.

Des Weiteren kann XSU Daten aus XML-Dokumenten extrahieren, um sie in Tabellen oder Views einzufügen. Auch das Extrahieren von Daten aus XML-Dokumenten für das Updaten oder Löschen von Zeilen in Tabellen oder Views steht zur Verfügung.

Außerdem sind seit Oracle 9i noch weitere Funktionen hinzugekommen, wie z. B. das Generieren eines XML-Schemas oder die Unterstützung von XML-Attributen.

XSU kann auf drei verschiedene Weisen verwendet werden:

Im Folgenden schauen wir uns an, wie XSU innerhalb von PL/SQL eingesetzt werden kann.

Oracle stellt zwei Pakete für die Verwendung von XSU in der Datenbank zur Verfügung:

Mit dem ersten Paket, DBMS_XMLQuery, hat man die Möglichkeit, eine XML-Ausgabe zu erzeugen. Die Verarbeitung wird in Abbildung 5 dargestellt.

DECLARE
   -- Objekte definieren
   queryCtx DBMS_XMLQuery.ctxType;
   ergebnis CLOB;
BEGIN
   -- neuen Kontext anlegen und SQL-Statement setzen
   queryCtx := DBMS_XMLQuery.newContext
   ('SELECT AUTO_ID, AUTO_NAME FROM auto');
   -- SQL-Statement ausführen und mit der Funktion
   -- getXML das XML-Dokument generieren.
   -- Das XML-Dokument wird in der Ergebnis-
   -- variablen erg vom Typ CLOB abgespeichert
   ergebnis := DBMS_XMLQuery.getXML(queryCtx);
   -- in Tabelle abspeichern
   INSERT INTO temp_clob VALUES (erg);
   -- Kontext schließen
   DBMS_XMLQuery.closeContext(queryCtx);
END;
/
Abb. 5: Generierung eines XML-Dokuments mit XSU.

Das Vorgehen ist hier ähnlich der Verwendung des Pakets DBMS_XMLGEN. Auch die Funktionen, die im Paket DBMS_XMLQuery zur Verfügung stehen, ähneln denen aus dem Paket DBMS_XMLGEN. Das Beispiel bezieht sich wieder auf die Tabelle auto, die unter DBMS_XMLGEN beschrieben wurde.

Auch beim zweiten Paket, DBMS_XMLQuery, erzeugen wir zunächst einen Context-Handle, der die Abfrage enthält. Das geschieht über die Funktion newContext des Pakets. Dann erzeugen wir unser Ergebnis, indem wir die Funktion getXML aufrufen und ihr den Context- Handle übergeben. Dieses Ergebnis speichern wir in die Tabelle temp_clob, um uns später durch einfaches Selektieren die Ausgabe des Ergebnisses zu vereinfachen.

Wenn wir diese Prozedur nun ausführen und das Ergebnis, welches in der Tabelle temp_ clob abgespeichert wurde, selektieren, bekommen wir die Ausgabe, die in Abbildung 6 dargestellt ist.

<?xml version="1.0" ?>
<ROWSET>
  <ROW num="1">
     <AUTO_ID>1</AUTO_ID>
     <AUTO_NAME>Alfa Romeo 156</AUTO_NAME>
  </ROW>
  <ROW num="2">
     <AUTO_ID>2</AUTO_ID>
     <AUTO_NAME>Alfa Romeo 147</AUTO_NAME>
  </ROW>
</ROWSET>
Abb. 6: XML-Dokument, welches mit XSU generiert wurde.

Beim Betrachten dieses Ergebnisses sehen wir, dass das Root-Element ROWSET und jedes Element, welches eine Ergebniszeile repräsentiert, ROW heißt. Dies sind die Default- Tags, wenn man die Tags für das RowSet bzw. das RowSetTag nicht, wie in unserem Beispiel zu DBMS_XMLGEN, definiert hat. Dies ist aber natürlich auch über Funktionen des Pakets DBMS_XMLQuery möglich. Auf diese Funktionen sind wir hier nicht eingegangen.

Mit DBMS_XMLSave kann man mittels einer XML-Eingabe einfügen, updaten und löschen. Dabei ist ganz besonders darauf zu achten, dass die Zieltabelle mit der XML-Struktur übereinstimmt, da es sonst bei der Verarbeitung zu Fehlern kommt. Die Zuordnung der Spalten zu den Elementen erfolgt über die Metadaten. Sprich: die Tags, die die einzufügenden Daten enthalten, müssen genauso heißen, wie die Spalten in der Datenbank, in denen sie abgespeichert werden sollen.

Unser Beispiel in Abbildung 7 beinhaltet den Quelltext der Prozedur insert_auto. Hierbei ist zu beachten, dass die Prozedur ein XML-Dokument in Form eines VARCHARs übergeben bekommt. Die weitere Verarbeitung ist analog zur Verarbeitung von DBMS_XMLQuery.

CREATE OR REPLACE PROCEDURE
   insert_auto(pXmlDoc IN VARCHAR2) IS
   insCtx DBMS_XMLSave.ctxType;
   rows NUMBER;
BEGIN
-- neuen Kontext anlegen und dabei den Namen der
-- Tabelle als Parameter übergeben
insCtx := DBMS_XMLSave.newContext( 'auto' );
-- Definition des Elementnamens, der den Inhalt
-- einer jeden Tabellenzeile enthält
DBMS_XMLSave.setRowTag(insCtx, 'Auto');
-- Insert in Tabelle auto ausführen - zurückgegeben
-- wird die Anzahl der eingefügten Zeilen
rows := DBMS_XMLSave.insertXML (insCtx , pXmlDoc);
-- Kontext schließen
DBMS_XMLSave.closeContext (insCtx);
END;
/
Abb. 7: Insert über XSU.

Aufgerufen wird diese Prozedur über eine anonyme Prozedur, die das zu übergebene XML-Dokument definiert (siehe Abbildung 8).

DECLARE
    myChar VARCHAR2(2000);
BEGIN
    MyChar := '<?xml version="1.0" ?>
      <Autoliste>
      <Auto>
        <Auto_ID>7</Auto_ID>
        <Auto_Name>
          Jaguar S-Type
        </Auto_Name>
      </Auto>
    </Autoliste>';
    insert_Auto(myChar);
END;
/
Abb. 8: Aufruf der Insert-Prozedur für den Insert über XSU.

Fazit

Oracle stellt eine stolze Anzahl von Komponenten zur Verfügung, die der Verwaltung und der Generierung von XML-Daten dienen. Die Prozeduren, die Oracle zum Generieren von XML-Dokumenten zur Verfügung stellt, stellen eine enorme Arbeitserleichterung dar, wenn man aus Daten der Datenbank XML-Dokumente erzeugen muss.

Mit Hilfe des Datentyps XMLType bieten sich viele weitere Möglichkeiten, die wir in einer der nächsten ORDIX News betrachten werden.

Auch das Abspeichern und Verwalten von XML-Daten in der Datenbank ist dank der von Oracle zur Verfügung gestellten Mittel um einiges performanter geworden. Abschließend lässt sich also sagen, dass Oracle mit dem XML-Support einen großen Teil zu einer einfachen Verarbeitung von XML in der Datenbank beigetragen hat.

Kathrin Hammerschmidt (info@ordix.de).