Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In SQL Server 2000 kann die FOR XML-Klausel nur auf der obersten Ebene einer SELECT-Abfrage angegeben werden. Der resultierende XML-Code wird in erster Linie an den Client zur weiteren Verarbeitung zurückgegeben. In SQL Server 2005 kann durch die Einführung des xml-Datentyps und der TYPE-Direktive in FOR XML-Abfragen der von den FOR XML-Abfragen zurückgegebene XML-Code auf dem Server weiter verarbeitet werden.
Sie können das Ergebnis einer FOR XML-Abfrage einer xml-Typvariablen zuweisen oder das Ergebnis mithilfe einer XQuery-Abfrage abfragen und das daraus entstehende Ergebnis einer xml-Typvariablen zur weiteren Verarbeitung zuweisen.
DECLARE @x xml SET @x=(SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID=122 or ProductModelID=119 FOR XML RAW, TYPE) SELECT @x -- Result --<row ProductModelID="122" Name="All-Purpose Bike Stand" /> --<row ProductModelID="119" Name="Bike Wash" />Sie können den in der Variablen
@xzurückgegebenen XML-Code zusätzlich verarbeiten, indem Sie eine der xml-Datentypmethoden verwenden. So können Sie z. B. mithilfe der value()-Methode (XML-Datentyp) den Attributwert vonProductModelIDabrufen.DECLARE @i int SET @i = (SELECT @x.value('/row[1]/@ProductModelID[1]', 'int')) SELECT @iIm folgenden Beispiel wird das Ergebnis der
FOR XML-Abfrage als xml-Typ zurückgegeben, da in derFOR XML-Klausel dieTYPE-Direktive angegeben wurde.SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID=119 or ProductModelID=122 FOR XML RAW, TYPE,ROOT('myRoot')Dies ist das Ergebnis:
<myRoot> <row ProductModelID="122" Name="All-Purpose Bike Stand" /> <row ProductModelID="119" Name="Bike Wash" /> </myRoot>Da das Ergebnis dem xml-Typ entspricht, können Sie eine der xml-Datentypmethoden direkt für diesen XML-Code angeben, wie es in der folgenden Abfrage gezeigt wird. In der Abfrage wird die Methode query() (XML-Datentyp) verwendet, um das erste untergeordnete <
row>-Element des Elements <myRoot> abzurufen.SELECT (SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID=119 or ProductModelID=122 FOR XML RAW, TYPE,ROOT('myRoot')).query('/myRoot[1]/row[1]')Dies ist das Ergebnis:
<row ProductModelID="122" Name="All-Purpose Bike Stand" />Sie können auch geschachtelte
FOR XML-Abfragen schreiben, bei denen das Ergebnis der inneren Abfrage als xml-Typ an die äußere Abfrage zurückgegeben wird. Beispiel:SELECT Col1, Col2, ( SELECT Col3, Col4 FROM T2 WHERE T2.Col = T1.Col ... FOR XML AUTO, TYPE ) FROM T1 WHERE ... FOR XML AUTO, TYPEBeachten Sie in der vorherigen Abfrage Folgendes:
- Der von der inneren
FOR XML-Abfrage generierte XML-Code wird dem von der äußerenFOR XML-Abfrage generierten XML-Code hinzugefügt. - Die innere Abfrage gibt die
TYPE-Direktive an. Die von der inneren Abfrage zurückgegebenen XML-Daten gehören daher dem xml-Typ an. Wenn die TYPE-Direktive nicht angegeben wird, wird das Ergebnis der innerenFOR XML-Abfrage als nvarchar(max) zurückgegeben, und die XML-Daten werden in Entitäten geändert.
Geschachtelte FOR XML-Abfragen ermöglichen eine bessere Steuerung der Form der resultierenden XML-Daten.
In SQL Server 2000 generieren im RAW- und AUTO-Modus ausgeführte Abfragen standardmäßig attributzentrierten XML-Code. Beispiel:
SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID=122 or ProductModelID=119 FOR XML RAWDies ist das attributzentrierte Ergebnis:
<row ProductModelID="122" Name="All-Purpose Bike Stand" /> <row ProductModelID="119" Name="Bike Wash" />Durch Angeben der
ELEMENTS-Direktive können Sie den gesamten XML-Code als elementzentrierten Code abrufen. Beispiel:SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID=122 or ProductModelID=119 FOR XML RAW, ELEMENTSDies ist das elementzentrierte Ergebnis:
<row> <ProductModelID>122</ProductModelID> <Name>All-Purpose Bike Stand</Name> </row> <row> <ProductModelID>119</ProductModelID> <Name>Bike Wash</Name> </row>Für geschachtelte FOR XML-Abfragen können Sie in SQL Server 2005 XML-Code konstruieren, der zum Teil attributzentriert und zum Teil elementzentriert ist.
In SQL Server 2000 können Sie gleichgeordnete Elemente nur durch Schreiben von Abfragen im EXPLICIT-Modus konstruieren. Dies kann jedoch sehr aufwändig sein. In SQL Server 2005 können Sie XML-Hierarchien generieren, die gleichgeordnete Elemente enthalten, indem Sie geschachtelte FOR XML-Abfragen im AUTO-Modus angeben.
Unabhängig davon, welchen Modus Sie verwenden, bieten geschachtelte FOR XML-Abfragen größere Steuerungsmöglichkeiten beim Beschreiben der Form des resultierenden XML-Codes. Diese Abfragen können anstelle von Abfragen im EXPLICIT-Modus verwendet werden.
- Der von der inneren
Beispiele
A. Vergleichen einer FOR XML-Abfrage mit einer geschachtelten FOR XML-Abfrage
Die folgende SELECT-Abfrage ruft Informationen zur Produktkategorie und Produktunterkategorie aus der AdventureWorks-Datenbank ab. In der Abfrage gibt es keine geschachtelte FOR XML-Anweisung.
SELECT ProductCategory.ProductCategoryID,
ProductCategory.Name as CategoryName,
ProductSubCategory.ProductSubCategoryID,
ProductSubCategory.Name
FROM Production.ProductCategory, Production.ProductSubCategory
WHERE ProductCategory.ProductCategoryID = ProductSubCategory.ProductCategoryID
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE
GO
Dies ist das Teilergebnis:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory ProductSubCategoryID="1" Name="Mountain Bike"/>
<ProductSubCategory ProductSubCategoryID="2" Name="Road Bike"/>
<ProductSubCategory ProductSubCategoryID="3" Name="Touring Bike"/>
</ProductCategory>
...
Wenn Sie die ELEMENTS-Direktive in der Abfrage angeben, erhalten Sie ein elementzentriertes Ergebnis, wie es im folgenden Ergebnisfragment gezeigt wird:
<ProductCategory>
<ProductCategoryID>1</ProductCategoryID>
<CategoryName>Bike</CategoryName>
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<Name>Mountain Bike</Name>
</ProductSubCategory>
<ProductSubCategory>
...
</ProductSubCategory>
</ProductCategory>
Gehen wir nun davon aus, dass Sie eine XML-Hierarchie generieren möchten, die eine Kombination aus attributzentriertem und elementzentriertem XML-Code darstellt, wie das im folgenden Fragment gezeigt wird:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
Im oben gezeigten Fragment sind die Informationen zur Produktkategorie (z. B. die Kategorie-ID und der Kategoriename) Attribute. Allerdings sind die Informationen zur Unterkategorie elementzentriert. Zum Konstruieren des <ProductCategory>-Elements können Sie eine FOR XML-Abfrage wie die folgende schreiben:
SELECT ProductCategoryID, Name as CategoryName
FROM Production.ProductCategory ProdCat
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE
Dies ist das Ergebnis:
< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />
Zum Konstruieren der geschachtelten <ProductSubCategory>-Elemente im angestrebten XML-Code fügen Sie anschließend eine geschachtelte FOR XML-Abfrage hinzu, wie es im folgenden Beispiel gezeigt wird:
SELECT ProductCategoryID, Name as CategoryName,
(SELECT ProductSubCategoryID, Name SubCategoryName
FROM Production.ProductSubCategory
WHERE ProductSubCategory.ProductCategoryID =
ProductCategory.ProductCategoryID
FOR XML AUTO, TYPE, ELEMENTS
)
FROM Production.ProductCategory
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE
Beachten Sie bei der vorstehenden Abfrage folgende Aspekte:
- Mit der inneren
FOR XML-Abfrage werden Informationen zur Produktunterkategorie abgerufen. DieELEMENTS-Direktive wird der innerenFOR XML-Abfrage hinzugefügt, um elementzentrierten XML-Code zu generieren, der dem von der äußeren Abfrage generierten XML-Code hinzugefügt wird. Standardmäßig generiert die äußere Abfrage attributzentrierten XML-Code. - In der inneren Abfrage wird die
TYPE-Direktive angegeben, sodass das Ergebnis den xml-Typ aufweist. WennTYPEnicht angegeben wird, wird das Ergebnis als nvarchar(max)-Typ zurückgegeben, und die XML-Daten werden als Entitäten zurückgegeben. - Die
TYPE-Direktive wird auch in der äußeren Abfrage angegeben. Deshalb wird das Ergebnis dieser Abfrage als xml-Typ an den Client zurückgegeben.
Dies ist das Teilergebnis:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
Die folgende Abfrage ist lediglich eine Erweiterung der vorherigen Abfrage. Sie zeigt die vollständige Produkthierarchie in der AdventureWorks-Datenbank. Dazu gehören:
- Produktkategorien
- Produktunterkategorien in jeder Kategorie
- Produktmodelle in jeder Unterkategorie
- Produkte in jedem Produktmodell
Die folgende Abfrage kann ggf. für das Verständnis der AdventureWorks-Datenbank nützlich sein:
SELECT ProductCategoryID, Name as CategoryName,
(SELECT ProductSubCategoryID, Name SubCategoryName,
(SELECT ProductModel.ProductModelID,
ProductModel.Name as ModelName,
(SELECT ProductID, Name as ProductName, Color
FROM Production.Product
WHERE Product.ProductModelID =
ProductModel.ProductModelID
FOR XML AUTO, TYPE)
FROM (SELECT distinct ProductModel.ProductModelID,
ProductModel.Name
FROM Production.ProductModel,
Production.Product
WHERE ProductModel.ProductModelID =
Product.ProductModelID
AND Product.ProductSubCategoryID =
ProductSubCategory.ProductSubCategoryID)
ProductModel
FOR XML AUTO, type
)
FROM Production.ProductSubCategory
WHERE ProductSubCategory.ProductCategoryID =
ProductCategory.ProductCategoryID
FOR XML AUTO, TYPE, ELEMENTS
)
FROM Production.ProductCategory
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE
Dies ist das Teilergebnis:
<Production.ProductCategory ProductCategoryID="1" CategoryName="Bikes">
<Production.ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bikes</SubCategoryName>
<ProductModel ProductModelID="19" ModelName="Mountain-100">
<Production.Product ProductID="771"
ProductName="Mountain-100 Silver, 38" Color="Silver" />
<Production.Product ProductID="772"
ProductName="Mountain-100 Silver, 42" Color="Silver" />
<Production.Product ProductID="773"
ProductName="Mountain-100 Silver, 44" Color="Silver" />
…
</ProductModel>
…
Wenn Sie die ELEMENTS-Direktive aus der geschachtelten FOR XML-Abfrage entfernen, mit der die Produktunterkategorien generiert werden, ist das gesamte Ergebnis attributzentriert. Sie können diese Abfrage dann ohne Schachtelung schreiben. Das Hinzufügen der ELEMENTS-Direktive ergibt einen XML-Code, der teilweise attributzentriert und teilweise elementzentriert ist. Dieses Ergebnis kann nicht durch eine FOR XML-Abfrage mit nur einer einzigen Ebene generiert werden.
B. Generieren von gleichgeordneten Elementen durch Verwenden einer geschachtelten Abfrage im AUTO-Modus
Im folgenden Beispiel wird das Generieren von gleichgeordneten Elementen durch Verwenden einer geschachtelten Abfrage im AUTO-Modus gezeigt. Die einzige Möglichkeit zum Generieren von derartigem XML-Code besteht im Verwenden des EXPLICIT-Modus. Dies kann jedoch sehr aufwendig sein.
Diese Abfrage konstruiert XML-Code, der Bestellinformationen bereitstellt. Dazu gehören:
- Kopfzeileninformationen der Bestellungen, die Bestellungs-ID (
SalesOrderID), die Vertriebsmitarbeiter-ID (SalesPersonID) und das Bestelldatum (OrderDate). AdventureWorks speichert diese Informationen in derSalesOrderHeader-Tabelle. - Detaillierte Bestellinformationen. Dazu gehören Angaben zu einem oder mehreren bestellten Produkten, zum Einzelpreis und zur bestellten Menge. Diese Informationen werden in der
SalesOrderDetail-Tabelle gespeichert. - Informationen zum Vertriebsmitarbeiter. Dies ist der Vertriebsmitarbeiter, der die Bestellung entgegengenommen hat. Die
SalesPerson-Tabelle stellt die Angaben fürSalesPersonIDbereit. Für diese Abfrage müssen Sie diese Tabelle mit derEmployee-Tabelle verknüpfen, um den Namen des Vertriebsmitarbeiters zu finden.
Die beiden folgenden unterschiedlichen SELECT-Abfragen generieren XML-Code, der in seiner Form einen kleinen Unterschied aufweist.
Die erste Abfrage generiert XML-Code, in dem <SalesPerson> und <SalesOrderHeader> als nebengeordnete Unterelemente von <SalesOrder> erscheinen:
SELECT
(SELECT top 2 SalesOrderID, SalesPersonID, CustomerID,
(select top 3 SalesOrderID, ProductID, OrderQty, UnitPrice
from Sales.SalesOrderDetail
WHERE SalesOrderDetail.SalesOrderID =
SalesOrderHeader.SalesOrderID
FOR XML AUTO, TYPE)
FROM Sales.SalesOrderHeader
WHERE SalesOrderHeader.SalesOrderID = SalesOrder.SalesOrderID
for xml auto, type),
(SELECT *
FROM (SELECT SalesPersonID, EmployeeID
FROM Sales.SalesPerson, HumanResources.Employee
WHERE SalesPerson.SalesPersonID = Employee.EmployeeID) As
SalesPerson
WHERE SalesPerson.SalesPersonID = SalesOrder.SalesPersonID
FOR XML AUTO, TYPE)
FROM (SELECT SalesOrderHeader.SalesOrderID, SalesOrderHeader.SalesPersonID
FROM Sales.SalesOrderHeader, Sales.SalesPerson
WHERE SalesOrderHeader.SalesPersonID = SalesPerson.SalesPersonID
) as SalesOrder
ORDER BY SalesOrder.SalesOrderID
FOR XML AUTO, TYPE
In der vorherigen Abfrage bewirkt die äußerste SELECT-Anweisung Folgendes:
- Sie fragt das Rowset
SalesOrderab, das in derFROM-Klausel angegeben ist. Das Ergebnis ist ein XML-Code mit einem oder mehreren <SalesOrder>-Elementen. - Sie gibt den
AUTO-Modus und dieTYPE-Direktive an. DerAUTO-Modus wandelt das Abfrageergebnis in XML-Code um, und dieTYPE-Direktive gibt das Ergebnis als xml-Typ zurück. - Sie schließt zwei geschachtelte
SELECT-Anweisungen ein, die durch ein Komma voneinander getrennt sind. Die erste geschachtelteSELECT-Anweisung ruft die Bestellinformationen (Kopfzeile und Details) ab, und die zweite geschachtelteSELECT-Anweisung ruft die Informationen zum Vertriebsmitarbeiter ab.- Die
SELECT-Anweisung, dieSalesOrderID,SalesPersonIDundCustomerIDabruft, enthält eine weitere geschachtelteSELECT ... FOR XML-Anweisung (mitAUTO-Modus undTYPE-Direktive), die Detailinformationen zur Bestellung zurückgibt.
- Die
Die SELECT-Anweisung, mit der die Informationen zum Vertriebsmitarbeiter abgerufen werden, fragt ein Rowset (SalesPerson) ab, das in der FROM-Klausel erstellt wird. Damit FOR XML-Abfragen funktionsfähig sind, müssen Sie einen Namen für das anonyme Rowset bereitstellen, das in der FROM-Klausel generiert wird. In diesem Fall ist der bereitgestellte Name SalesPerson.
Dies ist das Teilergebnis:
<SalesOrder>
<Sales.SalesOrderHeader SalesOrderID="43659" SalesPersonID="279" CustomerID="676">
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="776" OrderQty="1" UnitPrice="2024.9940" />
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="777" OrderQty="3" UnitPrice="2024.9940" />
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="778" OrderQty="1" UnitPrice="2024.9940" />
</Sales.SalesOrderHeader>
<SalesPerson SalesPersonID="279" EmployeeID="279" />
</SalesOrder>
...
Die folgende Abfrage generiert dieselben Bestellinformationen, außer dass im resultierenden XML-Code das <SalesPerson>-Element als nebengeordnetes Element von <SalesOrderDetail> erscheint:
<SalesOrder>
<SalesOrderHeader ...>
<SalesOrderDetail .../>
<SalesOrderDetail .../>
...
<SalesPerson .../>
</SalesOrderHeader>
</SalesOrder>
<SalesOrder>
...
</SalesOrder>
Im Folgenden wird die Abfrage aufgeführt:
SELECT SalesOrderID, SalesPersonID, CustomerID,
(select top 3 SalesOrderID, ProductID, OrderQty, UnitPrice
from Sales.SalesOrderDetail
WHERE SalesOrderDetail.SalesOrderID = SalesOrderHeader.SalesOrderID
FOR XML AUTO, TYPE),
(SELECT *
FROM (SELECT SalesPersonID, EmployeeID
FROM Sales.SalesPerson, HumanResources.Employee
WHERE SalesPerson.SalesPersonID = Employee.EmployeeID) As SalesPerson
WHERE SalesPerson.SalesPersonID = SalesOrderHeader.SalesPersonID
FOR XML AUTO, TYPE)
FROM Sales.SalesOrderHeader
WHERE SalesOrderID=43659 or SalesOrderID=43660
FOR XML AUTO, TYPE
Dies ist das Ergebnis:
<Sales.SalesOrderHeader SalesOrderID="43659" SalesPersonID="279" CustomerID="676">
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="776" OrderQty="1" UnitPrice="2024.9940" />
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="777" OrderQty="3" UnitPrice="2024.9940" />
<Sales.SalesOrderDetail SalesOrderID="43659" ProductID="778" OrderQty="1" UnitPrice="2024.9940" />
<SalesPerson SalesPersonID="279" EmployeeID="279" />
</Sales.SalesOrderHeader>
<Sales.SalesOrderHeader SalesOrderID="43660" SalesPersonID="279" CustomerID="117">
<Sales.SalesOrderDetail SalesOrderID="43660" ProductID="762" OrderQty="1" UnitPrice="419.4589" />
<Sales.SalesOrderDetail SalesOrderID="43660" ProductID="758" OrderQty="1" UnitPrice="874.7940" />
<SalesPerson SalesPersonID="279" EmployeeID="279" />
</Sales.SalesOrderHeader>
Da die TYPE-Direktive Abfrageergebnisse als xml-Typ zurückgibt, können Sie den resultierenden XML-Code mithilfe verschiedener xml-Datentypmethoden abfragen. Weitere Informationen finden Sie unter XML-Datentypmethoden. Beachten Sie in der nächsten Abfrage Folgendes:
Die vorherige Abfrage wird in der
FROM-Klausel hinzugefügt. Das Abfrageergebnis wird als Tabelle zurückgegeben. Beachten Sie den hinzugefügtenXmlCol-Alias.Die
SELECT-Klausel gibt eine XQuery-Abfrage fürXmlColan, das in derFROM-Klausel zurückgegeben wird. Die XQuery-Abfrage wird mit der query()-Methode des xml-Datentyps angegeben. Weitere Informationen finden Sie unter query()-Methode (xml-Datentyp).SELECT XmlCol.query('<Root> { /* } </Root>') FROM ( SELECT SalesOrderID, SalesPersonID, CustomerID, (select top 3 SalesOrderID, ProductID, OrderQty, UnitPrice from Sales.SalesOrderDetail WHERE SalesOrderDetail.SalesOrderID = SalesOrderHeader.SalesOrderID FOR XML AUTO, TYPE), (SELECT * FROM (SELECT SalesPersonID, EmployeeID FROM Sales.SalesPerson, HumanResources.Employee WHERE SalesPerson.SalesPersonID = Employee.EmployeeID) As SalesPerson WHERE SalesPerson.SalesPersonID = SalesOrderHeader.SalesPersonID FOR XML AUTO, TYPE) FROM Sales.SalesOrderHeader WHERE SalesOrderID='43659' or SalesOrderID='43660' FOR XML AUTO, TYPE ) as T(XmlCol)
C. Erstellen einer ASPX-Anwendung zum Abrufen von Bestellinformationen im Browser
Im folgenden Beispiel führt eine ASPX-Anwendung eine gespeicherte Prozedur aus und gibt Bestellinformationen als XML-Code zurück. Das Ergebnis wird im Browser angezeigt. Die SELECT-Anweisung in der gespeicherten Prozedur entspricht der Anweisung in Beispiel B, außer dass der resultierende XML-Code elementzentriert ist.
CREATE PROC GetSalesOrderInfo AS
SELECT
(SELECT top 2 SalesOrderID, SalesPersonID, CustomerID,
(select top 3 SalesOrderID, ProductID, OrderQty, UnitPrice
from Sales.SalesOrderDetail
WHERE SalesOrderDetail.SalesOrderID = SalesOrderHeader.SalesOrderID
FOR XML AUTO, TYPE)
FROM Sales.SalesOrderHeader
WHERE SalesOrderHeader.SalesOrderID = SalesOrder.SalesOrderID
for xml auto, type),
(SELECT *
FROM (SELECT SalesPersonID, EmployeeID
FROM Sales.SalesPerson, HumanResources.Employee
WHERE SalesPerson.SalesPersonID = Employee.EmployeeID) As SalesPerson
WHERE SalesPerson.SalesPersonID = SalesOrder.SalesPersonID
FOR XML AUTO, TYPE, ELEMENTS)
FROM (SELECT SalesOrderHeader.SalesOrderID, SalesOrderHeader.SalesPersonID
FROM Sales.SalesOrderHeader, Sales.SalesPerson
WHERE SalesOrderHeader.SalesPersonID = SalesPerson.SalesPersonID
) as SalesOrder
ORDER BY SalesOrder.SalesOrderID
FOR XML AUTO, TYPE
GO
Dies ist die ASPX-Anwendung. Sie führt die gespeicherte Prozedur aus und gibt den XML-Code im Browser zurück:
<%@LANGUAGE=C# Debug=true %>
<%@import Namespace="System.Xml"%>
<%@import namespace="System.Data.SqlClient" %><%
Response.Expires = -1;
Response.ContentType = "text/xml";
%>
<%
using(System.Data.SqlClient.SqlConnection c = new System.Data.SqlClient.SqlConnection("Data Source=server;Database=AdventureWorks;Integrated Security=SSPI;"))
using(System.Data.SqlClient.SqlCommand cmd = c.CreateCommand())
{
cmd.CommandText = "GetSalesOrderInfo";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
System.Xml.XmlReader r = cmd.ExecuteXmlReader();
System.Xml.XmlTextWriter w = new System.Xml.XmlTextWriter(Response.Output);
w.WriteStartElement("Root");
r.MoveToContent();
while(! r.EOF)
{
w.WriteNode(r, true);
}
w.WriteEndElement();
w.Flush();
}
%>
So testen Sie die Anwendung
- Erstellen Sie die gespeicherte Prozedur in der AdventureWorks-Datenbank.
- Speichern Sie die ASPX-Anwendung in c:\inetpub\wwwroot-Verzeichnis (GetSalesOrderInfo.aspx).
- Führen Sie die Anwendung aus (https://server/GetSalesOrderInfo.aspx).
D. Konstruieren von XML-Code, der die Produktpreise einschließt
Das folgende Beispiel ist eine Abfrage der Production.Product-Tabelle zum Abrufen der Werte von ListPrice und StandardCost eines bestimmten Produkts. Damit die Abfrage interessant wird, werden beide Preise in einem <Price>-Element zurückgegeben, und jedes <Price>-Element verfügt über ein PriceType-Attribut. Der erwartete XML-Code hat die folgende Form:
<xsd:schema xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet2" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Production.Product" type="xsd:anyType" />
</xsd:schema>
<Production.Product xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2" ProductID="520">
<Price PriceType="ListPrice">133.34</Price>
<Price PriceType="StandardCost">98.77</Price>
</Production.Product>
Dies ist die geschachtelte FOR XML-Abfrage:
SELECT Product.ProductID,
(SELECT 'ListPrice' as PriceType,
CAST(CAST(ListPrice as NVARCHAR(40)) as XML)
FROM Production.Product Price
WHERE Price.ProductID=Product.ProductID
FOR XML AUTO, TYPE),
(SELECT 'StandardCost' as PriceType,
CAST(CAST(StandardCost as NVARCHAR(40)) as XML)
FROM Production.Product Price
WHERE Price.ProductID=Product.ProductID
FOR XML AUTO, TYPE)
FROM Production.Product
WHERE ProductID=520
for XML AUTO, TYPE, XMLSCHEMA
Beachten Sie in der vorherigen Abfrage Folgendes:
- Die äußere SELECT-Anweisung konstruiert das <
Product>-Element, das über ein ProductID-Attribut und zwei untergeordnete <Price>-Elemente verfügt. - Die beiden inneren SELECT-Anweisungen konstruieren zwei <
Price>-Elemente, von denen jedes über ein PriceType-Attribut verfügt, sowie XML-Code, der den Produktpreis zurückgibt. - Die XMLSCHEMA-Direktive in der äußeren SELECT-Anweisung generiert das XSD-Inlineschema, das die Form des resultierenden XML-Codes beschreibt.
Um die Abfrage interessant zu machen, können Sie die FOR XML-Abfrage schreiben und dann eine XQuery-Abfrage für das Ergebnis schreiben, um den XML-Code umzuformen, wie das in der folgenden Abfrage gezeigt wird:
SELECT ProductID,
( SELECT p2.ListPrice, p2.StandardCost
FROM Production.Product p2
WHERE Product.ProductID = p2.ProductID
FOR XML AUTO, ELEMENTS XSINIL, type ).query('
for $p in /p2/*
return
<Price PriceType = "{local-name($p)}">
{ data($p) }
</Price>
')
FROM Production.Product
WHERE ProductID = 520
FOR XML AUTO, TYPE
Im oben gezeigten Beispiel wird die query()-Methode des xml-Datentyps verwendet, um den durch die innere FOR XML-Abfrage zurückgegebenen XML-Code abzufragen und das erwartete Ergebnis zu konstruieren.
Dies ist das Ergebnis:
<Production.Product ProductID="520">
<Price PriceType="ListPrice">133.3400</Price>
<Price PriceType="StandardCost">98.7700</Price>
</Production.Product>