Бөлісу құралы:


ЗАПРОС FOR XML по сравнению с вложенным ЗАПРОСом FOR XML

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

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

Примеры кода Transact-SQL в этой статье используют AdventureWorks2022 базу данных или AdventureWorksDW2022 пример базы данных, которую можно скачать с домашней страницы примеров и проектов сообщества Microsoft SQL Server.

Примеры

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

USE AdventureWorks2022;
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-данных, которая сочетает атрибутивную и элементную модели, как показано в следующем фрагменте:

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

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

  • Категории продуктов
  • Подкатегории продукции в каждой категории
  • Модели продуктов в каждой подкатегории
  • Продукты в каждой модели

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

SELECT ProductCategoryID,
    Name AS CategoryName,
    (
        SELECT ProductSubCategoryID,
            Name AS 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 запроса.