Поделиться через


Сравнение запросов FOR XML и вложенных запросов FOR XML

В этом разделе сравнивается одноуровневый запрос FOR XML с вложенным запросом FOR XML. Одним из преимуществ вложенных запросов FOR XML является то, что в них для результатов запроса можно задать сочетание XML-данных по атрибутивной или элементной модели. Это демонстрируется в примере.

Пример

Следующий запрос SELECT позволяет получить сведения о категории и подкатегории продукта в базе данных База данных AdventureWorks2008R2. В запросе нет вложенных запросов FOR XML.

USE AdventureWorks2008R2;
GO
SELECT   ProductCategory.ProductCategoryID, 
         ProductCategory.Name as CategoryName,
         ProductSubcategory.ProductSubcategoryID, 
         ProductSubcategory.Name
FROM     Production.ProductCategory
INNER JOIN Production.ProductSubcategory
    ON 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-данных, которая сочетает атрибутивную и элементную модели, как показано в следующем фрагменте:

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

Для создания необходимых вложенных элементов <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-данные по атрибутивной модели.

  • Во внутреннем запросе указана директива 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>

Следующий запрос представляет собой расширение предыдущего запроса. Он показывает полную иерархию продуктов в базе данных База данных AdventureWorks2008R2. Это включает следующее:

  • Категории продукции

  • Подкатегории продукции в каждой категории

  • Модели продуктов в каждой подкатегории

  • Продукты в каждой модели

Следующий пример может быть полезен для понимания базы данных База данных AdventureWorks2008R2:

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>

Если удалить директиву ELEMENTS из вложенного запроса FOR XML, который создает подкатегории продуктов, то весь результат будет создан по атрибутивной модели. Этот запрос можно составить без вложений. Добавление директивы ELEMENTS приводит к созданию XML-документа как по атрибутивной, так и по элементной модели. Этот результат нельзя сформировать с помощью одноуровневого запроса FOR XML.

См. также

Справочник