Beispiele: Verwenden des PATH-Modus

Gilt für:SQL ServerAzure SQL-DatenbankAzure SQL Managed Instance

Diese Beispiele veranschaulichen die Verwendung des PATH-Modus beim Generieren von XML-Code aus einer SELECT-Abfrage. Viele dieser Abfragen beziehen sich auf die XML-Dokumente mit den Fahrradfertigungsanweisungen, die in der Instructions-Spalte der ProductModel-Tabelle gespeichert sind.

Angeben einer PATH-Modusabfrage

Diese Abfrage gibt einen FOR XML PATH-Modus an.

USE AdventureWorks2022;
GO
SELECT
       ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH;
GO

Das folgende Ergebnis ist elementzentrierter XML-Code, wobei jeder Spaltenwert des resultierenden Rowsets in ein Element eingebunden wird. Da die SELECT Klausel keine Aliase für die Spaltennamen angibt, sind die generierten untergeordneten Elementnamen mit den entsprechenden Spaltennamen in der SELECT Klausel identisch. Für jede Zeile im Rowset wird ein <row> Tag hinzugefügt.

<row>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</row>
<row>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</row>

Das folgende Ergebnis ist mit dem der Abfrage im RAW -Modus mit angegebener Option ELEMENTS identisch. Es gibt elementorientiertes XML mit einem Standardelement <row> für jede Zeile im Resultset zurück.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML RAW, ELEMENTS;

Optional können Sie den Zeilenelementnamen angeben, um den Standardnamen <row>zu überschreiben. Die folgende Abfrage gibt z. B. das <ProductModel> Element für jede Zeile im Rowset zurück.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModel');
GO

Das XML-Ergebnis weist den angegebenen Zeilenelementnamen auf.

<ProductModel>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</ProductModel>
<ProductModel>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</ProductModel>

Wenn Sie eine leere Zeichenfolge angeben, wird das Umbruchelement nicht erstellt.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH ('');
GO

Dies ist das Ergebnis:

<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>

Angeben von XPath-ähnlichen Spaltennamen

In der folgenden Abfrage beginnt der ProductModelID angegebene Spaltenname mit '@' und enthält keine Schrägstriche ('/'). Daher wird ein Attribut des <row> Elements mit dem entsprechenden Spaltenwert im resultierenden XML erstellt.

USE AdventureWorks2022;
GO
SELECT ProductModelID AS "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH ('ProductModelData');
GO

Dies ist das Ergebnis:

<ProductModelData id="122">
  <Name>All-Purpose Bike Stand</Name>
</ProductModelData>
<ProductModelData id="119">
  <Name>Bike Wash</Name>
</ProductModelData>

Sie können ein einzelnes Element auf höchster Ebene hinzufügen, indem Sie in root die Option FOR XMLangeben.

SELECT ProductModelID AS "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData'), root ('Root');
GO

Um eine Hierarchie zu generieren, können Sie eine PATH-ähnliche Syntax einfügen. Ändern Sie beispielsweise den Spaltennamen für die Name Spalte in "SomeChild/ModelName", und Sie erhalten XML mit Hierarchie, wie in diesem Ergebnis gezeigt:

<Root>
  <ProductModelData id="122">
    <SomeChild>
      <ModelName>All-Purpose Bike Stand</ModelName>
    </SomeChild>
  </ProductModelData>
  <ProductModelData id="119">
    <SomeChild>
      <ModelName>Bike Wash</ModelName>
    </SomeChild>
  </ProductModelData>
</Root>

Außer der ID und dem Namen des Produktmodells ruft die folgende Abfrage die Speicherorte der Fertigungsanweisungen dieses Produktmodells ab. Da die Spalte "Anweisungen" vom XML-Typ ist, wird die query() Methode des XML-Datentyps angegeben, um den Speicherort abzurufen.

SELECT ProductModelID AS "@id",
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location
              ') AS ManuInstr
FROM Production.ProductModel
WHERE ProductModelID = 7
FOR XML PATH ('ProductModelData'), root ('Root');
GO

Dies ist das Teilergebnis. Da die Abfrage ManuInstr als Spaltennamen angibt, wird der von der query() Methode zurückgegebene XML-Code in ein <ManuInstr> Tag eingeschlossen, wie in der folgenden Abbildung gezeigt:

<Root>
  <ProductModelData id="7">
    <Name>HL Touring Frame</Name>
    <ManuInstr>
      <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
        <MI:step>...</MI:step>...
      </MI:Location>
      ...
    </ManuInstr>
  </ProductModelData>
</Root>

In der vorherigen FOR XML-Abfrage möchten Sie möglicherweise Namespaces für die und <ProductModelData> die <Root> Elemente einschließen. Dies erreichen Sie, indem Sie zunächst mithilfe von WITH XMLNAMESPACES das an den Namespace zu bindende Präfix definieren und das Präfix anschließend in der FOR XML-Abfrage verwenden. Weitere Informationen finden Sie unter Hinzufügen von Namespaces zu Abfragen mit WITH XMLNAMESPACES.

USE AdventureWorks2022;
GO
WITH XMLNAMESPACES (
   'uri1' AS ns1,
   'uri2' AS ns2,
   'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' as MI)
SELECT ProductModelID AS "ns1:ProductModelID",
       Name           AS "ns1:Name",
       Instructions.query('
                /MI:root/MI:Location
              ')
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ns2:ProductInfo'), root('ns1:root');
GO

Das MI Präfix wird auch in der WITH XMLNAMESPACES. Daher definiert die query() angegebene Methode des angegebenen XML-Typs das Präfix im Abfrageprolog nicht. Dies ist das Ergebnis:

<ns1:root xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns2:ProductInfo>
    <ns1:ProductModelID>7</ns1:ProductModelID>
    <ns1:Name>HL Touring Frame</ns1:Name>
    <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10" xmlns="">
    <MI:step>
      Insert <MI:material>aluminum sheet MS-2341</MI:material> into the <MI:tool>T-85A framing tool</MI:tool>.
    </MI:step>
    ...
    </MI:Location>
    ...
  </ns2:ProductInfo>
</ns1:root>

Generieren einer Wertliste mithilfe des PATH-Modus

Diese Abfrage konstruiert für jedes Produktmodell eine Wertliste mit Produkt-IDs. Für jede Produkt-ID erstellt <ProductName> die Abfrage auch geschachtelte Elemente, wie in diesem XML-Fragment dargestellt:

<ProductModelData ProductModelID="7" ProductModelName="..." ProductIDs="product id list in the product model">
  <ProductName>...</ProductName>
  <ProductName>...</ProductName>
  ...
</ProductModelData>

Im Folgenden wird die Abfrage gezeigt, die den gewünschten XML-Code erstellt:

USE AdventureWorks2022;
GO
SELECT ProductModelID     AS "@ProductModelID",
       Name               AS "@ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')) AS "@ProductIDs",
       (SELECT Name AS "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
        FOR XML PATH ('')) AS "ProductNames"
FROM   Production.ProductModel
WHERE  ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData');

Beachten Sie hinsichtlich der vorherigen Abfrage Folgendes:

  • Das erste geschachtelte SELECT gibt eine Liste von Product-IDs zurück und verwendet dabei data() als Spaltennamen. Da die Abfrage eine leere Zeichenfolge für den Namen des Zeilenelements in FOR XML PATHangibt, wird kein Element generiert. Stattdessen wird die Wertliste dem ProductID -Attribut zugewiesen.

  • Das zweite geschachtelte SELECT ruft die Produktnamen der Produkte des Produktmodells auf. Es generiert <ProductName> Elemente, die in das <ProductNames> Element eingeschlossen werden, da die Abfrage als Spaltenname angibt ProductNames .

Dies ist das Teilergebnis:

<ProductModelData PId="7" ProductModelName="HL Touring Frame" ProductIDs="885 887 ...">
  <ProductNames>
    <ProductName>HL Touring Frame - Yellow, 60</ProductName>
    <ProductName>HL Touring Frame - Yellow, 46</ProductName>
  </ProductNames>
  ...
</ProductModelData>
<ProductModelData PId="9" ProductModelName="LL Road Frame" ProductIDs="722 723 724 ...">
  <ProductNames>
    <ProductName>LL Road Frame - Black, 58</ProductName>
    <ProductName>LL Road Frame - Black, 60</ProductName>
    <ProductName>LL Road Frame - Black, 62</ProductName>
    ...
  </ProductNames>
</ProductModelData>

Die die Produktnamen konstruierende Unterabfrage gibt das Ergebnis als Zeichenfolge zurück, die in eine Entität geändert und anschließend dem XML-Code hinzugefügt wird. Wenn Sie die TYPE-Direktive FOR XML PATH (''), typehinzufügen, gibt die Unterabfrage das Ergebnis als XML -Typ zurück, und es erfolgt keine Änderung in Entitäten.

USE AdventureWorks2022;
GO
SELECT ProductModelID AS "@ProductModelID",
      Name AS "@ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) AS "@ProductIDs",
       (
       SELECT Name AS "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH (''), type
       ) AS "ProductNames"

FROM Production.ProductModel
WHERE ProductModelID= 7 OR ProductModelID=9
FOR XML PATH('ProductModelData');

Hinzufügen von Namespaces im resultierenden XML

Wie unter Hinzufügen von Namespaces mit WITH XMLNAMESPACESbeschrieben, können Sie WITH XMLNAMESPACES verwenden, um Namespaces in Abfragen im PATH-Modus aufzunehmen. Angenommen, die in der SELECT-Klausel angegebenen Namen enthalten Namespacepräfixe. Die folgende Abfrage im PATH -Modus konstruiert dieses XML-Ergebnis mit Namespaces.

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation')
GO

Das @xml:lang Attribut, das dem <English> Element hinzugefügt wird, wird im vordefinierten XML-Namespace definiert.

Dies ist das Ergebnis:

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

Die folgende Abfrage ist der in Beispiel C ähnlich, mit dem Unterschied, dass sie WITH XMLNAMESPACES verwendet, um Namespaces in das XML-Ergebnis einzuschließen. Weitere Informationen finden Sie unter Hinzufügen von Namespaces zu Abfragen mit WITH XMLNAMESPACES.

USE AdventureWorks2022;
GO
WITH XMLNAMESPACES ('uri1' AS ns1,  DEFAULT 'uri2')
SELECT ProductModelID AS "@ns1:ProductModelID",
      Name AS "@ns1:ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) AS "@ns1:ProductIDs",
       (
       SELECT ProductID AS "@ns1:ProductID",
              Name AS "@ns1:ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH , type
       ) AS "ns1:ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 OR ProductModelID=9
FOR XML PATH('ProductModelData'), root('root');

Dies ist das Ergebnis:

<root xmlns="uri2"
  xmlns:ns1="uri1">
  <ProductModelData ns1:ProductModelID="7" ns1:ProductModelName="HL Touring Frame" ns1:ProductIDs="885 887 888 889 890 891 892 893">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="885" ns1:ProductName="HL Touring Frame - Yellow, 60" />
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="887" ns1:ProductName="HL Touring Frame - Yellow, 46" />
      ...
    </ns1:ProductNames>
  </ProductModelData>
  <ProductModelData ns1:ProductModelID="9" ns1:ProductModelName="LL Road Frame" ns1:ProductIDs="722 723 724 725 726 727 728 729 730 736 737 738">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="722" ns1:ProductName="LL Road Frame - Black, 58" />
      ...
    </ns1:ProductNames>
  </ProductModelData>
</root>

Siehe auch