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


Сравнение запроса 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, как показано в следующем фрагменте:

<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> элементы в нужном XML-коде, добавьте вложенный 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>  

Следующий запрос — это просто расширение предыдущего запроса. В ней показана полная иерархия продуктов в базе данных 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>  
     ...  

При удалении ELEMENTS директивы из вложенного FOR XML запроса, создающего подкатегории продукта, весь результат ориентирован на атрибут. Этот запрос можно затем написать без вложения. Добавление ELEMENTS приводит к XML, который частично ориентирован на атрибуты и частично на элементы. Этот результат нельзя создать с помощью одноуровневого ЗАПРОСА FOR XML.

См. также

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