Mit FOR XML EXPLICIT können Sie die Struktur des XML-Dokuments steuern, das von der Abfrage zurückgegeben wird. Die Abfrage muss auf eine bestimmte Art geschrieben werden, um die Informationen über die gewünschte Verschachtelung innerhalb des Abfrageergebnisses anzugeben. Mit den von FOR XML EXPLICIT unterstützten optionalen Direktiven können Sie die Behandlung einzelner Spalten konfigurieren. So können Sie zum Beispiel steuern, ob eine Spalte als Element- oder Attributinhalt erscheint, oder ob eine Spalte nur zur Reihung des Ergebnisses verwendet wird und nicht im generierten XML vorkommt.
Im EXPLICIT-Modus müssen die ersten beiden Spalten in der SELECT-Anweisung Tag bzw. Parent benannt sein. "Tag" und "Parent" sind Metadaten-Spalten, deren Werte dazu verwendet werden, in diesen Spalten die Parent-/Child-Objektbeziehungen (Verschachtelung) der Elemente im XML-Dokument festzulegen, das von der Abfrage zurückgegeben wird.
Tag-Spalte Dies ist die erste in der SELECT-Liste angegebene Spalte. Die Tag-Spalte speichert die Tag-Nummer des aktuellen Elements. Zulässige Werte für Tag-Nummern sind 1 bis 255.
Parent-Spalte Diese Spalte speichert die Tag-Nummer für das übergeordnete Objekt des aktuellen Elements. Wenn der Wert in dieser Spalte NULL ist, wird die Zeile auf die oberste Ebene in der XML-Hierarchie platziert.
Nehmen wir zum Beispiel eine Abfrage, die die folgende Ergebnismenge zurückgibt, wobei FOR XML EXPLICIT nicht angegeben ist:
Tag | Parent | GivenName!1 | ID!2 |
---|---|---|---|
1 | NULL | 'Beth' | NULL |
2 | NULL | NULL | '102' |
In diesem Beispiel sind die Werte in der Tag-Spalte die Nummern der jeweiligen Elemente in der Ergebnismenge. Die Parent-Spalte für beide Zeilen enthält den Wert NULL. Beide Elemente werden in der obersten Ebene der Hierarchie generiert, was das folgende Ergebnis ergibt, wenn die Abfrage die FOR XML EXPLICIT-Klausel enthält:
<GivenName>Beth</GivenName> <ID>102</ID> |
Wenn allerdings die zweite Zeile in der Parent-Spalte den Wert 1 hat, sieht das Ergebnis folgendermaßen aus:
<GivenName>Beth <ID>102</ID> </GivenName> |
Zusätzlich zu den Tag- und Parent-Spalten muss die Abfrage eine oder mehrere Datenspalten enthalten. Die Namen dieser Datenspalten steuern, wie die Spalten während der Tag-Zuordnung interpretiert werden. Jeder Spaltenname wird in Felder aufgeteilt, die durch ein Ausrufzeichen (!) voneinander getrennt sind. Die folgenden Felder können für Datenspalten angegeben werden:
ElementName!TagNumber!AttributeName!Directive
ElementName Der Name des Elements. Bei einer gegebenen Zeile wird der Name des Elements, das für die Zeile generiert wird, dem Feld ElementName der ersten Spalte mit der übereinstimmenden Tag-Nummer entnommen. Wenn es mehrere Spalten mit derselben TagNumber gibt, wird der ElementName bei nachfolgenden Spalten mit derselben TagNumber ignoriert. Im vorigen Beispiel generiert die erste Zeile ein Element mit dem Namen <GivenName>.
TagNumber Die Tag-Nummer des Elements. Bei einer Zeile mit einem gegebenen Tag-Wert werden alle Spalten mit demselben Wert in ihrem TagNumber-Feld Inhalte dem Element beisteuern, das der Zeile entspricht.
AttributeName Gibt an, dass der Spaltenwert ein Attribut des ElementName-Elements ist. Wenn zum Beispiel eine Datenspalte den Namen "productID!1!Color" hätte, dann würde "Color" (Farbe) als ein Attribut des <productID>-Elements erscheinen.
Directive Mit diesem optionalen Feld können Sie das Format des XML-Dokuments zusätzlich steuern. Sie können einen der folgenden Werte für Directive angeben:
hide Gibt an, dass diese Spalte bei der Generierung des Ergebnisses ignoriert wird. Mit dieser Direktive können Sie Spalten aufnehmen, die nur zur Reihung der Tabelle verwendet werden. Der Attributname wird ignoriert und kommt im Ergebnis nicht vor.
element Gibt an, dass die Spalte als ein verschachteltes Element mit dem Namen AttributeName eingefügt ist, und nicht als Attribut.
xml Gibt an, dass die Spalte ohne Anführungszeichen eingefügt wird. Wenn der AttributeName angegeben ist, wird der Wert als ein Element mit diesem Namen eingefügt. Ansonsten wird er ohne Einfassungselement eingefügt. Wenn diese Direktive nicht verwendet wird, werden Markup-Zeichen in Escapezeichen gesetzt, außer die Spalte ist vom Typ XML. Beispiel: Der Wert <a/> würde als <a/> eingefügt werden.
cdata Gibt an, dass der Spaltenwert als ein CDATA-Abschnitt eingefügt werden soll. Der AttributeName wird ignoriert.
Daten in BINARY-, LONG BINARY-, IMAGE- und VARBINARY-Spalten werden automatisch im base64-kodierten Format zurückgegeben, wenn Sie eine Abfrage ausführen, die FOR XML EXPLICIT enthält. Standardmäßig wird NULL in der Ergebnismenge weggelassen. Sie können dieses Verhalten ändern, indem Sie die Einstellungen der Option "for_xml_null_treatment" ändern.
Nehmen wir an, Sie wollen eine Abfrage unter Verwendung von FOR XML EXPLICIT schreiben, die das folgende XML-Dokument generiert:
<employee employeeID='129'> <customer customerID='107' region='Eastern'/> <customer customerID='119' region='Western'/> <customer customerID='131' region='Eastern'/> </employee> <employee employeeID='195'> <customer customerID='109' region='Eastern'/> <customer customerID='121' region='Central'/> </employee> |
Sie erreichen dies, indem Sie eine SELECT-Anweisung schreiben, die die folgende Ergebnismenge exakt in der angegebenen Reihenfolge zurückgibt, und dann FOR XML EXPLICIT an die Abfrage anhängen.
Tag | Parent | employee!1!employeeID | customer!2!customerID | customer!2!region |
---|---|---|---|---|
1 | NULL | 129 | NULL | NULL |
2 | 1 | 129 | 107 | Eastern |
2 | 1 | 129 | 119 | Western |
2 | 1 | 129 | 131 | Central |
1 | NULL | 195 | NULL | NULL |
2 | 1 | 195 | 109 | Eastern |
2 | 1 | 195 | 121 | Central |
Wenn Sie Ihre Abfrage schreiben, werden nur einige Spalten einer gegebenen Zeile Teil des generierten XML-Dokuments. Eine Spalte wird in das XML-Dokument nur aufgenommen, wenn der Wert im TagNumber-Feld (das zweite Feld im Spaltennamen) mit dem Wert in der Tag-Spalte übereinstimmt.
In diesem Beispiel wird die dritte Spalte für die zwei Zeilen verwendet, die den Wert 1 in ihrer Tag-Spalte haben. In der vierten und fünften Spalte werden die Werte für die Zeilen verwendet, die den Wert 2 in ihrer Tag-Spalte haben. Die Elementnamen werden dem ersten Feld im Spaltennamen entnommen. In diesem Fall werden <employee>- und <customer>-Elemente erstellt.
Die Attributnamen kommen aus dem dritten Feld im Spaltennamen. Daher wird für <employee>-Elemente ein employeeID-Attribut erstellt, während für <customer>-Elemente customerID- und region-Attribute generiert werden.
Die folgenden Schritte beschreiben, wie Sie unter Verwendung der SQL Anywhere-Beispieldatenbank die FOR XML EXPLICIT-Abfrage konstruieren, die ein XML-Dokument generiert, das jenem am Beginn dieses Abschnitts ähnelt.
Schreiben Sie eine SELECT-Anweisung, um die obersten Elemente zu generieren.
In diesem Beispiel generiert die erste SELECT-Anweisung in der Abfrage die <employee>-Elemente. Die ersten zwei Werte in der Abfrage müssen die Tag- und Parent-Spaltenwerte sein. Das <employee>-Element ist an der Spitze der Hierarchie und bekommt daher einen Tag-Wert von 1 und einen Parent-Wert von NULL zugeordnet.
Wenn Sie eine Abfrage im EXPLICIT-Modus schreiben, die einen UNION verwendet, dann werden nur die Spaltennamen verwendet, die in der ersten SELECT-Anweisung angegeben werden. Spaltennamen, die als Element- oder Attributnamen verwendet werden sollen, müssen in der ersten SELECT-Anweisung angegeben werden, weil Spaltennamen ignoriert werden, die in nachfolgenden SELECT-Anweisungen angegeben werden.
Um die <employee>-Elemente für die oben stehende Tabelle zu generieren, sieht Ihre erste SELECT-Anweisung folgendermaßen aus:
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!employeeID], NULL AS [customer!2!customerID], NULL AS [customer!2!region] FROM Employees; |
Schreiben Sie eine SELECT-Anweisung, um die untergeordneten Elemente zu generieren.
Die zweite Abfrage generiert die <customer>-Elemente. Da es sich um eine Abfrage im EXPLICIT-Modus handelt, müssen die ersten zwei in allen SELECT-Anweisungen angegebenen Werte die Tag- und Parent-Werte sein. Das <customer>-Element erhält die Tag-Nummer 2, und da es dem <employee>-Element untergeordnet ist, ist sein Parent-Wert 1. Die erste SELECT-Anweisung hat bereits festgelegt, dass "EmployeeID", "CustomerID" und "Region" Attribute sind.
SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders |
Fügen Sie der Abfrage UNION DISTINCT hinzu, um die beiden SELECT-Anweisungen miteinander zu vereinen.
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!employeeID], NULL AS [customer!2!customerID], NULL AS [customer!2!region] FROM Employees UNION DISTINCT SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders |
Fügen Sie eine ORDER BY-Klausel hinzu, um die Reihenfolge der Zeilen im Ergebnis festzulegen. Die Reihenfolge der Zeilen ist jene, die im resultierenden Dokument verwendet wird.
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!employeeID], NULL AS [customer!2!customerID], NULL AS [customer!2!region] FROM Employees UNION DISTINCT SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders ORDER BY 3, 1 FOR XML EXPLICIT; |
Die folgende Beispielabfrage ruft Informationen über die von Mitarbeitern getätigten Bestellungen ab. In diesem Beispiel gibt es drei Elemente: <employee>, <order> und <department>. Das <employee>-Element hat ID- und Namensattribute, das <order>-Element hat ein Datumsattribut, und das <department>-Element hat ein Namensattribut.
SELECT 1 tag, NULL parent, EmployeeID [employee!1!id], GivenName [employee!1!name], NULL [order!2!date], NULL [department!3!name] FROM Employees UNION DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
Diese Abfrage erzeugt das folgende Ergebnis:
<employee id="102" name="Fran"> <department name="R & D"/> </employee> <employee id="105" name="Matthew"> <department name="R & D"/> </employee> <employee id="129" name="Philip"> <order date="2000-07-24"/> <order date="2000-07-13"/> <order date="2000-06-24"/> <order date="2000-06-08"/> ... <department name="Sales"/> </employee> <employee id="148" name="Julie"> <department name="Finance"/> </employee> ... |
Um Unterelemente statt Attributen zu generieren, können Sie die "element"-Direktive zur Abfrage hinzufügen, und zwar folgendermaßen:
SELECT 1 tag, NULL parent, EmployeeID [employee!1!id!element], GivenName [employee!1!name!element], NULL [order!2!date!element], NULL [department!3!name!element] FROM Employees UNION DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
Diese Abfrage erzeugt das folgende Ergebnis:
<employee> <id>102</id> <name>Fran</name> <department> <name>R & D</name> </department> </employee> <employee> <id>105</id> <name>Matthew</name> <department> <name>R & D</name> </department> </employee> <employee> <id>129</id> <name>Philip</name> <order> <date>2000-07-24</date> </order> <order> <date>2000-07-13</date> </order> <order> <date>2000-06-24</date> </order> ... <department> <name>Sales</name> </department> </employee> ... |
In der folgenden Abfrage wird die EmployeeID zur Reihung des Ergebnisses verwendet, aber die EmployeeID selbst erscheint nicht im Ergebnis, weil die hide-Direktive (Ausblenden) angegeben ist:
SELECT 1 tag, NULL parent, EmployeeID [employee!1!id!hide], GivenName [employee!1!name], NULL [order!2!date], NULL [department!3!name] FROM Employees UNION DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
Diese Abfrage liefert das folgende Ergebnis:
<employee name="Fran"> <department name="R & D"/> </employee> <employee name="Matthew"> <department name="R & D"/> </employee> <employee name="Philip"> <order date="2000-04-21"/> <order date="2001-07-23"/> <order date="2000-12-30"/> <order date="2000-12-20"/> ... <department name="Sales"/> </employee> <employee name="Julie"> <department name="Finance"/> </employee> ... |
Wenn das Ergebnis einer FOR XML EXPLICIT-Abfrage Zeichen enthält, die keine gültigen XML-Zeichen sind, werden die unzulässigen Zeichen standardmäßig mit Escapezeichen versehen, außer die Spalte ist vom Typ XML. Hinweise finden Sie unter Regeln für die Codierung unzulässiger XML-Namen.
Beispiel: Die folgende Abfrage generiert XML, das ein kaufmännisches Und (&) enthält:
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!id!element], CompanyName AS [customer!1!company!element] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
Im von dieser Abfrage generierten Ergebnis wird das kaufmännische Und in Escapezeichen gesetzt, weil die Spalte nicht vom Typ XML ist:
<customer><id>115</id> <company>Sterling & Co.</company> </customer> |
Die xml-Direktive gibt an, dass der Spaltenwert ohne Escape-Zeichen in das generierte XML eingefügt wird. Führen Sie dieselbe Abfrage wie oben mit der xml-Direktive aus:
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!id!element], CompanyName AS [customer!1!company!xml] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
Für das kaufmännische Und-Zeichen wird im Ergebnis kein Escape-Zeichen gesetzt:
<customer> <id>115</id> <company>Sterling & Co.</company> </customer> |
Dieses XML ist nicht wohlgeformt, weil es ein kaufmännisches Und enthält, das ein Sonderzeichen in XML ist. Wenn XML von einer Abfrage generiert wird, liegt es in Ihrer Verantwortung, dass das XML wohlgeformt und gültig ist. SQL Anywhere überprüft nicht, ob das generierte XML wohlgeformt und gültig ist.
Wenn Sie die xml-Direktive angeben, wird das AttributeName-Feld verwendet, um Elemente statt Attribute zu generieren.
Die folgende Abfrage verwendet die cdata-Direktive, um den Kundennamen in einen CDATA-Abschnitt zurückzugeben:
SELECT 1 AS tag, NULL AS parent, ID AS [product!1!id], Description AS [product!1!!cdata] FROM Products FOR XML EXPLICIT; |
Das von dieser Abfrage erzeugte Ergebnis listet die Beschreibung für jedes Produkt in einem CDATA-Abschnitt auf. Im CDATA-Abschnitt enthaltene Daten werden nicht in Anführungszeichen gesetzt:
<product id="300"> <![CDATA[Tank Top]]> </product> <product id="301"> <![CDATA[V-neck]]> </product> <product id="302"> <![CDATA[Crew Neck]]> </product> <product id="400"> <![CDATA[Cotton Cap]]> </product> ... |
![]() |
Kommentieren Sie diese Seite in DocCommentXchange.
|
Copyright © 2013, SAP AG oder ein SAP-Konzernunternehmen. - SAP Sybase SQL Anywhere 16.0 |