Consulta FOR XML comparada com consulta FOR XML aninhada
Este tópico 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 isso.
Exemplo
A consulta SELECT a seguir recupera informações de categoria e subcategoria de produtos no banco de dados do AdventureWorks. Não há nenhum FOR XML aninhado na consulta.
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 diretiva ELEMENTS na consulta, receberá um resultado centrado em elemento, conforme mostrado no fragmento de resultado a seguir:
<ProductCategory>
<ProductCategoryID>1</ProductCategoryID>
<CategoryName>Bike</CategoryName>
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<Name>Mountain Bike</Name>
</ProductSubCategory>
<ProductSubCategory>
...
</ProductSubCategory>
</ProductCategory>
Em seguida, assuma que você quer gerar uma hierarquia XML que seja uma combinação de XML centrado em atributo e em elemento, conforme mostrado no fragmento a seguir:
<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
Este é o resultado:
< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />
Para construir elementos <ProductSubCategory> aninhados no XML desejado, adicione uma consulta FOR XML aninhada, conforme mostrado a seguir:
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
Observe o seguinte na consulta anterior:
A consulta FOR XML interna recupera informações de subcategoria de produtos. A diretiva ELEMENTS é adicionada ao FOR 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. Se TYPE 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 AdventureWorks. Isso inclui o seguinte:
Categorias de produtos
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 AdventureWorks:
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
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.