Share via


Verwenden des PATH-Modus

Wie unter Erstellen von XML mithilfe von FOR XML beschrieben, bietet der PATH-Modus ein vereinfachtes Verfahren zum Mischen von Elementen und Attributen. Außerdem eignet sich der PATH-Modus auch dazu, auf einfache Weise zusätzliche Schachtelungen zum Darstellen komplexer Eigenschaften einzuführen. Sie können Abfragen im FOR XML EXPLICIT-Modus verwenden, um einen solchen XML-Code aus einem Rowset zu konstruieren; der PATH-Modus stellt jedoch eine einfachere Alternative zu den potenziell aufwendigen Abfragen im EXPLICIT-Modus bereit. Der PATH-Modus bietet zusammen mit der Möglichkeit, geschachtelte FOR XML-Abfragen zu schreiben, und der TYPE-Direktive zum Zurückgeben von Instanzen vom Typ xml eine weniger komplexe Option zum Schreiben von Abfragen.

Im PATH-Modus werden Spaltennamen und Spaltenaliasse als XPath-Ausdrücke behandelt. Diese Ausdrücke zeigen an, wie die Werte dem XML-Code zugeordnet werden. Jeder XPath-Ausdruck ist ein relativer XPath, der den Typ des Elements bereitstellt, wie z. B. das Attribut, das Element, den skalaren Wert sowie den Namen und die Hierarchie des Knotens, der in Zusammenhang mit dem Zeilenelement generiert werden soll.

Dieses Thema beschreibt die folgenden Bedingungen für das Zuordnen von Spalten in einem Rowset, wobei folgende Spaltenarten berücksichtigt werden:

  • Spalten ohne Namen
  • Spalten mit Namen
  • Spalten mit als Platzhalterzeichen (*) angegebenen Namen
  • Spalten mit Namen von XPath-Knotentests
  • Spaltennamen, deren Pfad als data() angegeben ist
  • Spalten, die standardmäßig einen NULL-Wert enthalten

Spalten ohne Namen

Spalten ohne Namen werden als Inlinespalten betrachtet. Beispielsweise werden namenlose Spalten für berechnete Spalten oder geschachtelte skalare Abfragen, die keinen Spaltenalias angeben, generiert. Wenn die Spalte vom Typ xml ist, wird der Inhalt dieser Datentypinstanz eingefügt. Anderenfalls wird der Inhalt der Spalte als Textknoten eingefügt.

SELECT 2+2
FOR XML PATH

Erstellen Sie diesen XML-Code. Standardmäßig wird im XML-Ergebnis für jede Zeile des Rowsets ein <row>-Element generiert. Dies entspricht dem RAW-Modus.

<row>4</row>

Die folgende Abfrage gibt ein Rowset mit drei Spalten zurück. Die dritte, namenlose Spalte enthält XML-Daten. Der PATH-Modus fügt eine Instanz des XML-Typs ein.

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

Dies ist das Teilergebnis:

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location ...LocationID="10" ...></MI:Location>
  <MI:Location ...LocationID="20" ...></MI:Location>
   ...
</row>

Spalten mit Namen

Im Folgenden werden die spezifischen Bedingungen aufgeführt, unter denen dem XML-Ergebnis mit Unterscheidung nach Groß-/Kleinschreibung Rowsetspalten mit Namen zugeordnet werden, wobei nach folgenden Spaltenarten unterschieden wird:

  • Der Spaltenname beginnt mit einem @-Zeichen.
  • Der Spaltenname beginnt nicht mit einem @-Zeichen.
  • Der Spaltenname beginnt nicht mit einem @-Zeichen und enthält einen Schrägstrich (/).
  • Mehrere Spalten verwenden dasselbe Präfix.
  • Eine Spalte hat einen unterschiedlichen Namen.

Der Spaltenname beginnt mit einem @-Zeichen

Wenn der Spaltenname mit einem @-Zeichen beginnt und keinen Schrägstrich (/) enthält, wird ein Attribut für das <row>-Element mit dem entsprechenden Spaltenwert erstellt. Die folgende Abfrage gibt beispielsweise ein Rowset mit zwei Spalten (@PmId, Name) zurück. Im resultierenden XML-Code wird dem entsprechenden <row>-Element ein PmId-Attribut hinzugefügt und diesem ein Wert aus ProductModelID zugewiesen.

SELECT ProductModelID as "@PmId",
       Name
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

Dies ist das Ergebnis:

<row PmId="7">
  <Name>HL Touring Frame</Name>
</row>

Beachten Sie, dass Attribute allen anderen Knotentypen, wie z. B. Elementknoten und Textknoten, auf derselben Ebene vorangestellt sein müssen. Die folgende Abfrage gibt einen Fehler zurück:

SELECT Name,
       ProductModelID as "@PmId"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

Der Spaltenname beginnt nicht mit einem @-Zeichen

Wenn der Spaltenname nicht mit einem @-Zeichen beginnt, kein XPath-Knotentest ist und keinen Schrägstrich (/) enthält, wird ein XML-Element als Unterelement des Zeilenelements (standardmäßig <row>) erstellt.

Die folgende Abfrage gibt den Spaltennamen result an. Folglich wird dem <row>-Element ein untergeordnetes <result>-Element hinzugefügt.

SELECT 2+2 as result
for xml PATH

Dies ist das Ergebnis:

<row>
  <result>4</result>
</row>

Die folgende Abfrage gibt den Spaltennamen ManuWorkCenterInformation für den XML-Code an, der von der für die Instructions-Spalte vom xml-Typ angegebenen XQuery zurückgegeben wurde. Folglich wird dem <row>-Element ein untergeordnetes <ManuWorkCenterInformation>-Element hinzugefügt.

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location 
              ') as ManuWorkCenterInformation
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

Dies ist das Ergebnis:

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <ManuWorkCenterInformation>
    <MI:Location ...LocationID="10" ...></MI:Location>
    <MI:Location ...LocationID="20" ...></MI:Location>
     ...
  </ManuWorkCenterInformation>
</row>

Der Spaltenname beginnt nicht mit einem @-Zeichen und enthält einen Schrägstrich (/)

Wenn der Spaltenname nicht mit einem @-Zeichen beginnt, jedoch einen Schrägstrich (/) enthält, zeigt der Spaltenname eine XML-Hierarchie. Lautet der Spaltenname beispielsweise "Name1/Name2/Name3.../Namen", repräsentiert jeder Namei einen im aktuellen Zeilenelement geschachtelten Elementnamen (für i=1) oder einen Elementnamen, der sich unter dem Element mit dem Namen i-1 befindet. Wenn Namen mit einem @-Zeichen beginnt, wird er einem Attribut des Namen-1-Elements zugeordnet.

Die folgende Abfrage gibt beispielsweise die ID und den Namen eines Mitarbeiters als komplexes Element EmpName zurück, welches zwei Vornamen und einen Nachnamen enthält (FirstName, MiddleName, LastName).

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

Die Spaltennamen werden als Pfad für die Konstruktion des XML-Codes im PATH-Modus verwendet. Der Name der Spalte, die die ID-Werte der Mitarbeiter enthält, beginnt mit einem @-Zeichen. Folglich wird dem <row>-Element ein EmpID-Attribut hinzugefügt. Alle anderen Spalten enthalten einen eine Hierarchie aufzeigenden Schrägstrich (/) im Spaltennamen. Der resultierende XML-Code weist ein untergeordnetes <EmpName>-Element unter dem <row>-Element auf. Das untergeordnete <EmpName>-Element besitzt seinerseits die untergeordneten Elemente <First>, <Middle> und <Last>.

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
</row>

Der zweite Vorname des Mitarbeiters ist ein NULL-Wert, welcher standardmäßig der Abwesenheit eines Elements oder Attributs zugeordnet ist. Wenn Sie jedoch möchten, dass für NULL-Werte Elemente generiert werden, können Sie die ELEMENTS-Direktive mit XSINIL angeben, wie in der folgenden Abfrage gezeigt.

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

Dies ist das Ergebnis:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

Standardmäßig generiert der PATH-Modus elementzentrierten XML-Code. Daher hat die Angabe der ELEMENTS-Direktive in einer Abfrage im PATH-Modus keine Wirkung. Die ELEMENTS-Direktive erweist sich jedoch in Verbindung mit XSINIL als nützlich, um Elemente für NULL-Werte zu generieren.

Die folgende Abfrage ruft außer der ID und dem Namen die Adresse eines Mitarbeiters ab. Gemäß dem Pfad in den Spaltennamen für Adressspalten wird dem <row>-Element ein untergeordnetes <Address>-Element hinzugefügt, und die Adressdetails werden als untergeordnetes Element des <Address>-Elements hinzugefügt.

SELECT EmployeeID   "@EmpID", 
       FirstName    "EmpName/First", 
       MiddleName   "EmpName/Middle", 
       LastName     "EmpName/Last",
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City         "Address/City"
FROM   HumanResources.Employee E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

Dies ist das Ergebnis:

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
</row>

Mehrere Spalten verwenden dasselbe Pfadpräfix

Wenn mehrere aufeinander folgende Spalten dasselbe Pfadpräfix gemeinsam haben, werden sie unter demselben Namen gruppiert. Werden verschiedene Namespacepräfixe verwendet, wird ein Pfad als verschieden betrachtet, auch wenn die Präfixe an denselben Namespace gebunden sind. In der vorherigen Abfrage haben die FirstName-, MiddleName- und LastName-Spalte das Präfix EmpName gemeinsam. Daher werden sie dem <EmpName>-Element als untergeordnete Elemente hinzugefügt. Dies ist auch für das <Address>-Element, das Sie im vorherigen Beispiel erstellt haben, der Fall.

Eine Spalte hat einen unterschiedlichen Namen

Wenn eine Spalte in einer Reihe von Spalten einen anderen Namen aufweist, wird die Gruppierung unterbrochen, wie in der folgenden, geänderten Abfrage gezeigt. Die Abfrage unterbricht die Gruppierung von FirstName, MiddleName und LastName, die in der vorherigen Abfrage angegeben waren, durch Hinzufügen der Adressspalten zwischen der FirstName- und der MiddleName-Spalte.

SELECT EmployeeID "@EmpID", 
       FirstName "EmpName/First", 
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City "Address/City",
       MiddleName "EmpName/Middle", 
       LastName "EmpName/Last"
FROM   HumanResources.EmployeeAddress E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

Folglich erstellt die Abfrage zwei <EmpName>-Elemente. Das erste <EmpName>-Element besitzt als untergeordnetes Element <FirstName> und das zweite <EmpName>-Element <MiddleName> und <LastName>.

Dies ist das Ergebnis:

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
  <EmpName>
    <Last>Achong</Last>
  </EmpName>
</row>

Spalten mit als Platzhalterzeichen angegebenen Namen

Wenn der angegebene Spaltenname aus einem Platzhalterzeichen (*) besteht, wird der Inhalt der betroffenen Spalte so eingefügt, als wäre kein Spaltenname angegeben. Wenn die Spalte nicht vom Typ xml ist, wird der Inhalt der Spalte als Textknoten eingefügt, wie im folgenden Beispiel gezeigt:

SELECT EmployeeID "@EmpID", 
       FirstName "*", 
       MiddleName "*", 
       LastName "*"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

Dies ist das Ergebnis:

<row EmpID="1">GustavoAchong</row>

Wenn die Spalte vom Typ xml ist, wird die entsprechende XML-Struktur eingefügt. Die folgende Abfrage gibt beispielsweise "*" als Name der Spalte an, die den XML-Code enthält, der von der XQuery für die Instructions-Spalte zurückgegeben wurde.

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
                /MI:root/MI:Location 
              ') as "*"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

Dies ist das Ergebnis. Der von der XQuery zurückgegebene XML-Code wird ohne Wrapperelement eingefügt.

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location LocationID="10">...</MI:Location>
  <MI:Location LocationID="20">...</MI:Location>
...
</row>

Spalten mit Namen von XPath-Knotentests

Wenn es sich bei dem Spaltennamen um einen der XPath-Knotentests handelt, wird der Inhalt zugeordnet, wie in der folgenden Tabelle gezeigt.

Wenn der Spaltenname ein XPath-Knotentest ist, wird der Inhalt dem entsprechenden Knoten zugeordnet. Wenn der SQL-Typ der Spalte xml ist, wird ein Fehler zurückgegeben.

Spaltenname Verhalten

text()

Für eine Spalte mit dem Namen text() wird der Zeichenfolgenwert in dieser Spalte als Textknoten hinzugefügt.

comment()

Für eine Spalte mit dem Namen comment() wird der Zeichenfolgenwert in dieser Spalte als XML-Kommentar hinzugefügt.

node()

Für eine Spalte mit dem Namen node() ist das Ergebnis mit dem eines Platzhalter-Spaltennamens (*) identisch.

processing-instruction(name)

Für eine Spalte mit dem Namen einer Verarbeitungsanweisung wird der Zeichenfolgenwert in dieser Spalte als PI-Wert für den Zielnamen der Verarbeitungsanweisung hinzugefügt.

Spaltennamen, deren Pfad als data() angegeben ist

Wenn der als Spaltenname angegebene Pfad "data()" ist, wird der Wert im generierten XML-Code als atomarer Wert behandelt. Dem XML-Code wird ein Leerzeichen hinzugefügt, wenn das nächste Element in der Serialisierung ebenfalls ein atomarer Wert ist. Dies erweist sich beim Erstellen von Listenelementen und Attributen als nützlich. Die folgende Abfrage ruft die Produktmodell-ID, den Namen des Produktmodells sowie die Liste der Produkte dieses Produktmodells ab.

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"
FROM  Production.ProductModel
WHERE ProductModelID= 7 
FOR XML PATH('ProductModelData')

Das geschachtelte SELECT ruft eine Liste mit Produkt-IDs ab. Als Spaltenname für die Produkt-IDs wird dabei "data()" angegeben. Da der PATH-Modus eine leere Zeichenfolge für den Namen des Zeilenelements angibt, wird kein Zeilenelement generiert. Stattdessen werden die Werte als die einem ProductIDs-Attribut zugewiesene Werte des <ProductModelData>-Zeilenelements des übergeordneten SELECT zurückgegeben. Dies ist das Ergebnis:

<ProductModelData ProductModelID="7" 
                  ProductModelName="HL Touring Frame" 
                  ProductIDs="885 887 888 889 890 891 892 893" />

Spalten, die standardmäßig einen NULL-Wert enthalten

Standardmäßig wird ein NULL-Wert in einer Spalte der Abwesenheit des Attributs, Knotens oder Elements zugeordnet. Dieses Standardverhalten kann durch das Anfordern eines elementzentrierten XML-Codes mithilfe der ELEMENTS-Direktive und der Angabe von XSINIL zum Hinzufügen von Elementen für NULL-Werte überschrieben werden, wie in der folgenden Abfrage gezeigt:

SELECT EmployeeID as "@EmpID", 
       FirstName  as "EmpName/First", 
       MiddleName as "EmpName/Middle", 
       LastName   as "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

Im Folgenden wird das Ergebnis gezeigt. Beachten Sie, dass das <Middle>-Element abwesend sein wird, wenn XSINIL nicht angegeben wird.

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

Unterstützung von Namespaces

In dieser Version wird die Unterstützung von Namespaces im PATH-Modus durch das Verwenden von WITH NAMESPACES bereitgestellt. Beispielsweise zeigt die folgende Abfrage die Syntax von WITH NAMESPACES, um einen Namespace ("a:") zu deklarieren, der in der nachfolgenden SELECT-Anweisung verwendet werden kann:

WITH XMLNAMESPACES('a' as a)
SELECT 1 as 'a:b'
FOR XML PATH

Beispiele:

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. Weitere Informationen zu diesen XML-Anweisungen finden Sie unter Darstellung des xml-Datentyps in der AdventureWorks-Datenbank.

A. Angeben einer einfachen Abfrage im PATH-Modus

Diese Abfrage gibt einen FOR XML PATH-Modus an.

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 Aliasse für die Spaltennamen angibt, sind die Namen der generierten untergeordneten Elemente mit denen der entsprechenden Spalten in der SELECT-Klausel identisch. Für jede Zeile des Rowsets 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 wird elementzentrierter XML-Code mit einem standardmäßigen <row>-Element für jede Zeile des Resultsets zurückgegeben.

SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML RAW, ELEMENTS

Optional können Sie den Namen des Zeilenelements angeben, um den Standardnamen, <row>, zu überschreiben. Die folgende Abfrage gibt beispielsweise das <ProductModel>-Element für jede Zeile des Rowsets zurück.

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 Wrapperelement nicht erstellt.

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>

B. Angeben von XPath-ähnlichen Spaltennamen

In der folgenden Abfrage beginnt der für ProductModelID angegebene Spaltenname mit dem @-Zeichen und enthält keinen Schrägstrich (/). Daher wird im XML-Ergebnis für das <row>-Element mit dem entsprechenden Spaltenwert ein Attribut erstellt.

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 FOR XML die Option root angeben.

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. Wenn Sie beispielsweise den Spaltennamen für die Name-Spalte zu "SomeChild/ModelName" ändern, erhalten Sie ein hierarchisiertes XML-Ergebnis, wie im Folgenden 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. Nachdem die Instructions-Spalte vom Typ xml ist, wird die query()-Methode vom xml-Datentyp 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 als Spaltenname ManuInstr angibt, wird der von der query()-Methode zurückgegebene XML-Code in ein <ManuInstr>-Tag eingebunden, wie im Folgenden 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 die vorherige FOR XML-Abfrage können Sie eventuell für das <Root>- und das <ProductModelData>-Element Namespaces 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 mithilfe von WITH XMLNAMESPACES.

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

Beachten Sie, dass das MI-Präfix auch in WITH XMLNAMESPACES definiert ist. Folglich definiert die query()-Methode des angegebenen xml-Typs das Präfix nicht im Abfrageprolog. 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" >
       <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>

C. Generieren einer Wertliste mithilfe des PATH-Modus

Diese Abfrage konstruiert für jedes Produktmodell eine Wertliste mit Produkt-IDs. Außerdem konstruiert die Abfrage für jede Produkt-ID geschachtelte <ProductName>-Elemente, wie im folgenden XML-Fragment gezeigt:

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

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 bei der vorstehenden Abfrage folgende Aspekte:

  • 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 PATH angibt, 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 eingebunden in das <ProductNames>-Element zurückgegeben werden, da die Abfrage ProductNames als Spaltennamen angibt.

Dies ist das Teilergebnis:

<ProductModelData PId="7" 
                  ProductModelName="HL Touring Frame" 
                  ProductIDs="885 887 ...">
  <ProductNames>
    &lt;ProductName&gt;HL Touring Frame - Yellow, 60&lt;/ProductName&gt;
    &lt;ProductName&gt;HL Touring Frame - Yellow, 46&lt;/ProductName&gt;</ProductNames>
    ...
</ProductModelData>
<ProductModelData PId="9" 
                  ProductModelName="LL Road Frame" 
                  ProductIDs="722 723 724 ...">
  <ProductNames>
     &lt;ProductName&gt;LL Road Frame - Black, 58&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 60&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 62&lt;/ProductName&gt;
     ...
  </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 hinzufügen, FOR XML PATH (''), type, gibt die Unterabfrage das Ergebnis als xml-Typ zurück, und es erfolgt keine Änderung in Entitäten.

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')

D. Hinzufügen von Namespaces zu XML-Ergebnissen

Wie unter Hinzufügen von Namespaces mit WITH XMLNAMESPACES beschrieben, 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 dem <English>-Element hinzugefügte @xml:lang-Attribut ist 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 mithilfe von WITH XMLNAMESPACES.

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

Verweis

Erstellen von XML mithilfe von FOR XML

Konzepte

Hinzufügen von Namespaces mithilfe von WITH XMLNAMESPACES

Andere Ressourcen

SELECT (Transact-SQL)

Hilfe und Informationen

Informationsquellen für SQL Server 2005