Consulta FOR XML comparada com consulta FOR XML aninhada
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure
Este artigo compara uma consulta FOR XML
de nível único com uma consulta FOR XML
aninhada. Um dos benefícios do uso de consultas FOR XML
aninhadas é que é possível especificar uma combinação de XML centrado em atributo e em elemento para resultados da consulta. O exemplo demonstra esse benefício.
Os exemplos de código do Transact-SQL deste artigo usa o banco de dados de exemplo AdventureWorks2022
ou AdventureWorksDW2022
, que pode ser baixado da home page Microsoft SQL Server Samples and Community Projects.
Exemplos
A consulta SELECT
a seguir recupera informações de categoria e subcategoria de produtos no banco de dados do AdventureWorks2022
. Não há qualquer FOR XML
aninhado na consulta.
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
Este é o resultado parcial:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory ProductSubCategoryID="1" Name="Mountain Bike"/>
<ProductSubCategory ProductSubCategoryID="2" Name="Road Bike"/>
<ProductSubCategory ProductSubCategoryID="3" Name="Touring Bike"/>
</ProductCategory>
...
Se você especificar a política ELEMENTS
na consulta, receberá um resultado centrado em elemento, conforme mostrado no seguinte fragmento de resultado:
<ProductCategory>
<ProductCategoryID>1</ProductCategoryID>
<CategoryName>Bike</CategoryName>
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<Name>Mountain Bike</Name>
</ProductSubCategory>
<ProductSubCategory>
...
</ProductSubCategory>
</ProductCategory>
Em seguida, suponha que você queira gerar uma hierarquia XML que seja uma combinação de XML centrado em atributo e em elemento, conforme mostrado neste fragmento:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
No fragmento anterior, as informações da categoria de produtos como ID e nome da categoria são atributos. No entanto as informações de subcategoria são centradas em elemento. Para construir o elemento <ProductCategory>
, você pode escrever uma consulta FOR XML
conforme mostrado a seguir:
SELECT ProductCategoryID,
Name AS CategoryName
FROM Production.ProductCategory ProdCat
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;
Eis o resultado:
< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />
Para construir os elementos <ProductSubCategory>
aninhados no XML desejado, adicione uma consulta FOR XML
aninhada, conforme mostrado no seguinte exemplo de código:
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;
Observe o seguinte na consulta anterior:
A consulta
FOR XML
interna recupera informações de subcategoria de produtos. A diretivaELEMENTS
é adicionada aoFOR XML
interno para gerar XML centrado em elemento que é adicionado ao XML gerado pela consulta externa. Por padrão, a consulta externa gera XML centrado em atributo.Na consulta interna, a diretiva
TYPE
é especificada de forma que o resultado seja do tipo xml . SeTYPE
não for especificado, o resultado será retornado como tipo nvarchar(max) e os dados XML serão retornados como entidades.A consulta externa também especifica a diretiva
TYPE
. Portanto o resultado dessa consulta é retornado ao cliente como tipo xml .
Este é o resultado parcial:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
A consulta a seguir é apenas uma extensão da consulta anterior. Ela mostra a hierarquia completa de produtos no banco de dados AdventureWorks2022
. Isso inclui:
- Categorias de produto
- Subcategorias de produtos em cada categoria
- Modelos de produtos em cada subcategoria
- Produtos em cada modelo
A consulta a seguir pode ser útil para entender o banco de dados 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;
Este é o resultado parcial:
<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>
...
Se você remover a diretiva ELEMENTS
da consulta FOR XML
aninhada que gera subcategorias de produtos, todo o resultado será centrado em atributo. Em seguida, você pode escrever esta consulta sem aninhamento. A adição de resultados de ELEMENTS
em um XML que é parcialmente centrado em atributo e em elemento. Esse resultado não pode ser gerado por uma consulta FOR XML
de nível único.