
| 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. |
XML-Dokumente können in Oracle auf verschiedene Arten gespeichert werden:
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.
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.
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; / |
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> |
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.
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; |
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.
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; / |
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> |
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; / |
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; / |
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).