Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (Deutsch) » SQL Anywhere Server - SQL-Benutzerhandbuch » XML in der Datenbank » XML in der Datenbank benutzen » Abfrageergebnisse als XML erhalten

 

FOR XML EXPLICIT verwenden

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.

Ein Beispiel dafür, wie Sie eine Abfrage mit FOR XML EXPLICIT schreiben, finden Sie unter Eine Abfrage im EXPLICIT-Modus schreiben.

Parameter

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   Das ist die erste in der Auswahlliste 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: (Der Zweck der GivenName!1- und ID!2-Datenspalten wird im folgenden Abschnitt (Datenspalten einer Abfrage hinzufügen) beschrieben).

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. Das bedeutet, dass beide Elemente in der obersten Ebene der Hierarchie generiert werden, 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>

Ein Beispiel dafür, wie Sie eine Abfrage mit FOR XML EXPLICIT schreiben, finden Sie unter Eine Abfrage im EXPLICIT-Modus schreiben.

Datenspalten einer Abfrage hinzufügen

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 beim Generieren 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.

    Ein Beispiel zur Verwendung der hide-Direktive finden Sie unter Die Hide-Direktive verwenden.

  • element   Gibt an, dass die Spalte als ein verschachteltes Element mit dem Namen AttributeName eingefügt ist, und nicht als Attribut.

    Ein Beispiel zur Verwendung der element-Direktive finden Sie unter Die Element-Direktive verwenden.

  • 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 &lt;a/&gt; eingefügt werden.

    Ein Beispiel zur Verwendung der xml-Direktive finden Sie unter Die xml-Direktive verwenden.

  • cdata   Gibt an, dass der Spaltenwert als ein CDATA-Abschnitt eingefügt werden soll. Der AttributeName wird ignoriert.

    Ein Beispiel zur Verwendung der cdata-Direktive finden Sie unter Das cdata-Direktiv verwenden.

Verwendungszweck

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.

Weitere Hinweise zur Option "for_xml_null_treatment" finden Sie unter for_xml_null_treatment-Option [Datenbank] und FOR XML und NULL.

Eine Abfrage im EXPLICIT-Modus schreiben

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 vom dritten Feld im Spaltennamen, daher wird ein EmployeeID-Attribut für die <employee>-Elemente erstellt, während CustomerID- und Region-Attribute für <customer>-Elemente 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.

♦  So schreiben Sie eine FOR XML EXPLICIT-Abfrage
  1. 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.

    Hinweis

    Wenn Sie eine Abfrage im EXPLICIT-Modus schreiben, die 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;
  2. 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
  3. Fügen Sie der Abfrage UNION ALL 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 ALL 
    SELECT
          2,
          1,
          EmployeeID,
          CustomerID,
          Region
    FROM Employees KEY JOIN SalesOrders
  4. 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 ALL 
    SELECT
          2,
          1,
          EmployeeID,
          CustomerID,
          Region
    FROM Employees KEY JOIN SalesOrders
    ORDER BY 3, 1
    FOR XML EXPLICIT;

Hinweise zur Syntax des EXPLICIT-Modus finden Sie unter Parameter.

FOR XML EXPLICIT-Beispiele

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 ALL 
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
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 &amp; D"/>
</employee>
<employee ID="105" name="Matthew">
   <department name="R &amp; 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>
...
Die Element-Direktive verwenden

Wenn Sie lieber Unterelemente statt Attribute generieren wollen, 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 ALL
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
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 &amp; D</name>
   </department>
</employee> 
<employee>
   <id>105</id>
   <name>Matthew</name>
   <department>
      <name>R &amp; 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>
...
Die Hide-Direktive verwenden

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 ALL 
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
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 &amp; D"/>
</employee>
<employee name="Matthew">
   <department name="R &amp; 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>
...
Die xml-Direktive verwenden

Wenn das Ergebnis einer FOR XML EXPLICIT-Abfrage Zeichen enthält, die keine gültigen XML-Zeichen sind, werden die unzulässigen Zeichen mit Escapezeichen versehen (Hinweise finden Sie unter Unzulässige XML-Namen kodieren), außer die Spalte ist vom Typ XML. 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!CompanyName]
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:

<Customers CompanyName="Sterling &amp; Co.">
   <ID>115</ID>
</Customers>

Die xml-Direktive gibt an, dass der Spaltenwert in das generierte XML ohne Anführungszeichen 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!CompanyName!xml]
FROM Customers
WHERE ID = '115'
FOR XML EXPLICIT;

Das kaufmännische Und-Zeichen wird im Ergebnis nicht in Anführungszeichen gesetzt:

<customer>
 <ID>115</ID>
 <CompanyName>Sterling & Co.</CompanyName>
</customer>

Beachten Sie, dass dieses XML nicht wohlgeformt ist, weil es ein kaufmännisches Und enthält, der 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 ignoriert, und es werden Elemente und keine Attribute generiert.

Das cdata-Direktiv verwenden

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>
...