ЗАПРОС 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
запроса.