FOR XML 查询与嵌套 FOR XML 查询的比较

本主题将单级 FOR XML 查询与嵌套 FOR XML 查询进行比较。 使用嵌套 FOR XML 查询的好处之一是,可以为查询结果指定以属性为中心的 XML 和以元素为中心的 XML 的组合。 该示例演示了这一点。

示例:

以下 SELECT 查询检索 AdventureWorks2012 数据库中的产品类别和子类别信息。 查询中没有嵌套的 FOR XML。

USE AdventureWorks2012;  
GO  
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 和以元素为中心的 XML 的组合,如以下片段所示:

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

在前面的片段中,产品类别信息(如类别 ID 和类别名称)是属性。 但是,子类别信息以元素为中心。 若要构造 <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 查询检索产品子类别信息。 该 ELEMENTS 指令被添加到内部 FOR XML 中,以生成以元素为中心的 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>  

以下查询只是上一个查询的扩展。 它显示 AdventureWorks2012 数据库中的完整产品层次结构。 其中包括:

  • 产品类别

  • 每个类别中的产品子类别

  • 每个子类别中的产品模型

  • 每个模型中的产品

你可能会发现以下查询有助于了解 AdventureWorks2012 数据库:

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 查询生成。

另请参阅

使用嵌套 FOR XML 查询