Comparación de la consulta FOR XML con la consulta FOR XML anidada
Se aplica a: SQL Server Azure SQL Database Azure SQL Managed Instance
En este artículo se compara una consulta FOR XML
con una consulta FOR XML
anidada. Una de las ventajas de usar consultas FOR XML
anidadas es que puede especificar una combinación de XML centrado en atributos y un XML centrado en elementos para los resultados de la consulta. En este ejemplo se demuestra esta ventaja.
Los ejemplos de código de Transact-SQL de este artículo utilizan la base de datos de ejemplo AdventureWorks2022
o AdventureWorksDW2022
, que se puede descargar desde la página principal de Ejemplos y proyectos de la comunidad de Microsoft SQL Server.
Ejemplos
La siguiente consulta SELECT
recupera información de categoría y subcategoría de productos de la base de datos AdventureWorks2022
. No hay FOR XML
anidado en la 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 es el conjunto de resultados parciales:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory ProductSubCategoryID="1" Name="Mountain Bike"/>
<ProductSubCategory ProductSubCategoryID="2" Name="Road Bike"/>
<ProductSubCategory ProductSubCategoryID="3" Name="Touring Bike"/>
</ProductCategory>
...
Si especifica la directiva ELEMENTS
en la consulta, recibirá un resultado centrado en elementos, como se muestra en el siguiente fragmento de resultados:
<ProductCategory>
<ProductCategoryID>1</ProductCategoryID>
<CategoryName>Bike</CategoryName>
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<Name>Mountain Bike</Name>
</ProductSubCategory>
<ProductSubCategory>
...
</ProductSubCategory>
</ProductCategory>
A continuación, imagine que desea generar una jerarquía XML que sea una combinación de XML centrado en atributos y centrado en elementos, como se muestra en el siguiente fragmento:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
En el fragmento anterior, la información de categoría de productos, como el Id. y el nombre de categoría, son atributos. Sin embargo, la información de subcategoría está centrada en elementos. Para construir el elemento <ProductCategory>
, puede escribir una consulta FOR XML
como se muestra a continuación:
SELECT ProductCategoryID,
Name AS CategoryName
FROM Production.ProductCategory ProdCat
ORDER BY ProductCategoryID
FOR XML AUTO, TYPE;
Este es el resultado:
< ProdCat ProductCategoryID="1" CategoryName="Bikes" />
< ProdCat ProductCategoryID="2" CategoryName="Components" />
< ProdCat ProductCategoryID="3" CategoryName="Clothing" />
< ProdCat ProductCategoryID="4" CategoryName="Accessories" />
Para construir los elementos <ProductSubCategory>
anidados en el XML que desee, debe agregar una consulta FOR XML
anidada, como se muestra en el siguiente ejemplo 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 lo siguiente en la consulta anterior:
La consulta
FOR XML
interna recupera información de subcategoría de productos. La directivaELEMENTS
se agrega a la consultaFOR XML
interna para generar el XML centrado en elementos que se agrega al XML generado por la consulta externa. De manera predeterminada, la consulta externa genera XML centrado en atributos.En la consulta interna, se especifica la directiva
TYPE
para que el resultado sea de tipo xml . Si no se especificaTYPE
, el resultado se devuelve como tipo nvarchar(max) y los datos XML se devuelven como entidades.La consulta externa especifica también la directiva
TYPE
. Por tanto, el resultado de esta consulta se devuelve al cliente como tipo xml .
Este es el conjunto de resultados parciales:
<ProductCategory ProductCategoryID="1" CategoryName="Bike">
<ProductSubCategory>
<ProductSubCategoryID>1</ProductSubCategoryID>
<SubCategoryName>Mountain Bike</SubCategoryName></ProductSubCategory>
<ProductSubCategory>
...
<ProductSubCategory>
...
</ProductCategory>
La consulta siguiente es solo una extensión de la anterior. Muestra la jerarquía de productos completa de la base de datos AdventureWorks2022
. Esto incluye:
- Categorías de productos
- Subcategorías de productos de cada categoría
- Modelos de productos en cada subcategoría
- Productos en cada modelo
Quizá encuentre útil la siguiente consulta para comprender la base de datos 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 es el conjunto de resultados parciales:
<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>
...
Si quita la directiva ELEMENTS
de la consulta FOR XML
anidada que genera subcategorías de productos, todo el resultado está centrado en atributos. Después puede escribir esta consulta sin anidar. La adición de ELEMENTS
da lugar a un XML parcialmente centrado en atributos y parcialmente centrado en elementos. Este resultado no se puede generar en un solo nivel, consulta FOR XML
.