Share via


巢狀 FOR XML 查詢

在 SQL Server 2000 中,您只能在 SELECT 查詢的最上層指定 FOR XML 子句。產生的 XML 主要會傳回給用戶端以進行其他處理。在 SQL Server 2005 中,引進了 xml 資料類型FOR XML 查詢中的 TYPE 指示詞,就可以在伺服器上另行處理 FOR XML 查詢傳回的 XML。

  • 您可以將 FOR XML 查詢結果指派給 xml 類型變數,或是使用 XQuery 以查詢結果,然後將那個結果指派給xml 類型變數以進行其他處理。

    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" />
    

    使用其中一種 xml 資料類型方法,您就可以再額外處理以變數 @x 傳回的 XML。例如,您可以使用 value() 方法 (XML 資料類型) 來擷取 ProductModelID 屬性值。

    DECLARE @i int
    SET @i = (SELECT @x.value('/row[1]/@ProductModelID[1]', 'int'))
    SELECT @i
    

    在下列範例中,因為已在 FOR XML 子句中指定 TYPE 指示詞,所以傳回的 FOR XML 查詢結果為 xml 類型。

    SELECT ProductModelID, Name
    FROM Production.ProductModel
    WHERE ProductModelID=119 or ProductModelID=122
    FOR XML RAW, TYPE,ROOT('myRoot')
    

    以下是結果:

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

    因為結果為 xml 類型,所以您可以直接對此 XML 指定其中一個 xml 資料類型方法,如以下查詢所示。在查詢中,會使用 query() 方法 (XML 資料類型) 來擷取 <myRoot> 元素的第一個 <row> 元素子項。

    SELECT  (SELECT ProductModelID, Name
             FROM Production.ProductModel
             WHERE ProductModelID=119 or ProductModelID=122
             FOR XML RAW, TYPE,ROOT('myRoot')).query('/myRoot[1]/row[1]')
    

    以下是結果:

    <row ProductModelID="122" Name="All-Purpose Bike Stand" />
    
  • 另外,您可以撰寫巢狀 FOR XML 查詢,其中內部查詢的結果會以 xml 類型傳回外部查詢。例如:

    SELECT Col1, 
           Col2, 
           ( SELECT Col3, Col4 
            FROM  T2
            WHERE T2.Col = T1.Col
            ...
            FOR XML AUTO, TYPE )
    FROM T1
    WHERE ...
    FOR XML AUTO, TYPE
    

    下列為上一個查詢的注意事項:

    • 以內部 FOR XML 查詢產生的 XML 會加入至外部 FOR XML 產生的 XML 中。
    • 內部查詢指定了 TYPE 指示詞。因此,內部查詢所傳回的 XML 資料為 xml 類型。如果未指定 TYPE 指示詞,會以 nvarchar(max) 傳回內部 FOR XML 查詢的結果,並實體化 XML 資料。

    巢狀 FOR XML 查詢可讓您有更多的控制權,以定義所產生 XML 資料的形狀。

    • 在 SQL Server 2000 中,RAW 和 AUTO 模式查詢預設會產生屬性中心的 XML。例如:

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

      屬性中心結果如下:

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

      您可以指定 ELEMENTS 指示詞,以元素中心方式擷取所有的 XML。例如:

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

      元素中心結果如下:

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

      對於 SQL Server 2005 中的巢狀 FOR XML 查詢,您可以建構部份為屬性中心、部份為元素中心的 XML。

    • 在 SQL Server 2000 中,您只能使用 EXPLICIT 模式撰寫查詢以建構同層級。但是,這可能會相當繁雜。在 SQL Server 2005 中,您可以指定巢狀 AUTO 模式 FOR XML 查詢來產生含有同層級的 XML 階層。

    不論您使用的模式為何,巢狀 FOR XML 查詢都能提供更多的控制權以描述所產生 XML 的形狀。它們可用來取代 EXPLICIT 模式查詢。

範例

A. 比較 FOR XML 查詢與巢狀 FOR XML 查詢

下列 SELECT 查詢會擷取 AdventureWorks 資料庫中的產品類別目錄及子類別目錄資訊。此查詢中沒有巢狀的 FOR XML。

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

以下是部份結果:

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory ProductSubCategoryID="1" Name="Mountain Bike"/>
  <ProductSubCategory ProductSubCategoryID="2" Name="Road Bike"/>
  <ProductSubCategory ProductSubCategoryID="3" Name="Touring Bike"/>
</ProductCategory>
...

如果在查詢中指定 ELEMENTS 指示詞,會收到元素中心的結果,如以下結果片段所示:

<ProductCategory>
  <ProductCategoryID>1</ProductCategoryID>
  <CategoryName>Bike</CategoryName>
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <Name>Mountain Bike</Name>
  </ProductSubCategory>
  <ProductSubCategory>
     ...
  </ProductSubCategory>
</ProductCategory>

接下來,假設您想要產生 XML 階層,結合屬性中心及元素中心的 XML,如以下片段所示:

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
  <ProductSubCategory>
     ...
  <ProductSubCategory>
     ...
</ProductCategory>

在前述片段中,類別目錄識別碼及類別目錄名稱等產品類別目錄資訊為屬性。但是,子類別目錄資訊是元素中心的。若要建構 <ProductCategory> 元素,您可以撰寫 FOR XML 查詢,如下所示:

SELECT ProductCategoryID, Name as CategoryName
FROM Production.ProductCategory ProdCat
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE

以下是結果:

< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />

若要在希望的 XML 中建構巢狀的 <ProductSubCategory> 元素,您可以接著加入巢狀 FOR XML 查詢,如下所示:

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

下列為上一個查詢的注意事項:

  • 內部 FOR XML 查詢會擷取產品子類別目錄資訊。在內部 FOR XML 中加入 ELEMENTS 指示詞,以產生元素中心的 XML,此 XML 已加入至外部查詢產生的 XML 中。根據預設,外部查詢會產生屬性中西的 XML。
  • 在內部查詢中,指定 TYPE 指示詞,那麼結果就會屬於 xml 類型。如果未指定 TYPE,則結果會以 nvarchar(max) 類型傳回,而 XML 資料會以實體傳回。
  • 外部查詢也可以指定 TYPE 指示詞。因此,此查詢的結果會以 xml 類型傳回給用戶端。.

以下是部份結果:

<ProductCategory ProductCategoryID="1" CategoryName="Bike">
  <ProductSubCategory>
    <ProductSubCategoryID>1</ProductSubCategoryID>
    <SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
  <ProductSubCategory>
     ...
  <ProductSubCategory>
     ...
</ProductCategory>

以下查詢只是前述查詢的延伸模組。它會顯示 AdventureWorks 資料庫的完整產品階層。這包含下列項目:

  • 產品類別目錄
  • 每個 類別目錄中的產品子類別目錄
  • 每個子類別目錄中的產品型號
  • 每個型號中的產品

以下查詢應該有助於瞭解 AdventureWorks 資料庫:

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

以下是部份結果:

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

如果從產生產品子類別目錄的巢狀 FOR XML 查詢移除 ELEMENTS 指示詞,整個結果將為屬性中心。然後您可以無套疊的方式撰寫此查詢加入 ELEMENTS 會使 XML 一部份為屬性中心,一部份為元素中心。此結果無法由單一層級、FOR XML 查詢產生。

B. 使用巢狀 AUTO 模式查詢產生同層級

以下範例顯示如何使用巢狀 AUTO 模式查詢產生同層級。其他產生這類 XML 的唯一方式是使用 EXPLICIT 模式。但是,這可能會相當繁雜。

此查詢會建構提供銷售訂單資訊的 XML。這包含下列項目:

  • 銷售訂單標頭資訊:SalesOrderIDSalesPersonIDOrderDateAdventureWorks 會將此資訊儲存在 SalesOrderHeader 資料表中。
  • 銷售訂單詳細資訊。這包括一或多項已訂購的產品、單價及訂購的數量。此項資訊是儲存在 SalesOrderDetail 資料表中。
  • 銷售人員資訊。這是承接訂單的銷售人員。SalesPerson 資料表提供 SalesPersonID。對於此查詢,您必須將此資料表聯結到 Employee 資料表,才能找到銷售人員的名稱。

下述的兩個相異 SELECT 查詢會產生外觀上有些許不同的 XML。

第一個查詢會產生 XML,而 <SalesPerson> 及 <SalesOrderHeader> 會顯示為 <SalesOrder> 的同層級子系:

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

在上一個查詢中,最外層 SELECT 陳述式會執行下列動作:

  • 查詢 FROM 子句中指定的資料列集 SalesOrder。結果是具有一或多個 <SalesOrder> 元素的 XML。
  • 指定 AUTO 模式與 TYPE 指示詞。AUTO 模式會將查詢結果轉換為 XML,而 TYPE 指示詞會以 xml 類型傳回結果。
  • 包括以逗號分隔的兩個巢狀 SELECT 陳述式。第一個巢狀 SELECT 陳述式會擷取銷售訂單資訊、標頭及詳細資料,而第二個巢狀 SELECT 陳述式會擷取銷售人員資訊。
    • 擷取 SalesOrderIDSalesPersonIDCustomerIDSELECT 陳述式本身,包含另一個會傳回銷售訂單詳細資訊的巢狀 SELECT ... FOR XML 陳述式 (具有 AUTO 模式與 TYPE 指示詞)。

擷取銷售人員資訊的 SELECT 陳述式,會查詢以 FROM 子句建立的資料列集 SalesPerson。為了要使 FOR XML 查詢能夠運作,您必須對以 FROM 子句產生的匿名資料列集提供名稱。在此情況下,提供的名稱為 SalesPerson

以下是部份結果:

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

以下查詢會產生相同的銷售訂單資訊,<SalesPerson> 在產生的 XML 中還會顯示為 <SalesOrderDetail> 的同層級:

<SalesOrder>
    <SalesOrderHeader ...>
          <SalesOrderDetail .../>
          <SalesOrderDetail .../>
          ...
          <SalesPerson .../>
    </SalesOrderHeader>
    
</SalesOrder>
<SalesOrder>
  ...
</SalesOrder>

以下為查詢:

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

以下是結果:

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

因為 TYPE 指示詞會以 xml 類型傳回查詢結果,所以您可以使用不同的 xml 資料類型方法查詢產生的 XML。如需詳細資訊,請參閱 XML 資料類型方法。在下列查詢中,請注意下列項目:

  • 先前的查詢已加入 FROM 子句中。查詢結果會以資料表傳回。請注意新增的 XmlCol 別名。

  • SELECT 子句會對 FROM 子句中傳回的 XmlCol 指定 XQuery。xml 資料類型的 query() 方法則用來指定 XQuery。如需詳細資訊,請參閱<query() 方法 (xml 資料類型)>。

    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. 建立 ASPX 應用程式以瀏覽器擷取銷售訂單資訊

在下列範例中,ASPX 應用程式會執行預存程序,並以 XML 傳回銷售訂單資訊。結果會以瀏覽器顯示。除了產生的 XML 是元素中心之外,預存程序中的 SELECT 陳述式跟範例 B 中的陳述式類似。

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

這是 .aspx 應用程式。其會執行預存程序並在瀏覽器中傳回 XML。

<%@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();
}
%>
若要測試應用程式
  1. AdventureWorks 資料庫中建立預存程序。
  2. 在 c:\inetpub\wwwroot 目錄中儲存 .aspx 應用程式 (GetSalesOrderInfo.aspx)。
  3. 執行應用程式 (https://server/GetSalesOrderInfo.aspx)。

D. 建構包含產品價格的 XML

以下範例會查詢 Production.Product 資料表,以擷取特定產品的 ListPriceStandardCost 值。兩個價格都會以 <Price> 元素傳回,而且每個 <Price> 元素都有一個 PriceType 屬性,使查詢值得關注。以下是預期的 XML 外觀:

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

以下是巢狀 FOR XML 查詢:

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

下列為上一個查詢的注意事項:

  • 外部 SELECT 陳述式會建構擁有 ProductID 屬性的 <Product> 元素,以及兩個 <Price> 子元素。
  • 兩個內部 SELECT 陳述式會建構兩個 <Price> 元素,每個都具有一個 PriceType 屬性與會傳回產品價格的 XML。
  • 外部 SELECT 陳述式中的 XMLSCHEMA 指示詞會產生內嵌的 XSD 結構描述,描述產生之 XML 的外觀。

您可以撰寫 FOR XML 查詢,然後對結果撰寫 XQuery 以重新安排 XML 的外觀,使查詢值得關注,如以下查詢所述:

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

先前的範例使用 xml 資料類型的 query() 方法,查詢內部 FOR XML 查詢傳回的 XML,並建構預期的結果。

結果如下:

<Production.Product ProductID="520">
  <Price PriceType="ListPrice">133.3400</Price>
  <Price PriceType="StandardCost">98.7700</Price>
</Production.Product>