Dar forma a XML con consultas FOR XML anidadas
El ejemplo siguiente consulta la tabla Production.Product para recuperar los valores ListPrice y StandardCost de un producto específico. Para hacer interesante la consulta, se devuelven ambos precios en un elemento <Price>, y cada elemento <Price> tiene un atributo PriceType.
Ejemplo
Esta es la forma esperada del XML:
<xsd:schema xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet2" elementFormDefault="qualified">
<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Production.Product" type="xsd:anyType" />
</xsd:schema>
<Production.Product xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2" ProductID="520">
<Price PriceType="ListPrice">133.34</Price>
<Price PriceType="StandardCost">98.77</Price>
</Production.Product>
Esta es la consulta FOR XML anidada:
USE AdventureWorks2008R2;
GO
SELECT Product.ProductID,
(SELECT 'ListPrice' AS PriceType,
CAST(CAST(ListPrice AS NVARCHAR(40)) AS XML)
FROM Production.Product Price
WHERE Price.ProductID=Product.ProductID
FOR XML AUTO, TYPE),
(SELECT 'StandardCost' AS PriceType,
CAST(CAST(StandardCost as NVARCHAR(40)) AS XML)
FROM Production.Product Price
WHERE Price.ProductID=Product.ProductID
FOR XML AUTO, TYPE)
FROM Production.Product
WHERE ProductID = 520
for XML AUTO, TYPE, XMLSCHEMA;
Observe lo siguiente en la consulta anterior:
La instrucción SELECT externa construye el elemento <Product> que tiene un atributo ProductID y dos secundarios <Price>.
Las dos instrucciones SELECT internas construyen dos elementos <Price>, cada uno con un atributo PriceType y XML que devuelve el precio del producto.
La directiva XMLSCHEMA de la instrucción SELECT externa genera el esquema XSD insertado que describe la forma del XML resultante.
Para hacer interesante la consulta, puede escribir la consulta FOR XML y después escribir una consulta XQuery para el resultado con el fin de cambiar la forma del XML, como se muestra en la siguiente consulta:
SELECT ProductID,
( SELECT p2.ListPrice, p2.StandardCost
FROM Production.Product p2
WHERE Product.ProductID = p2.ProductID
FOR XML AUTO, ELEMENTS XSINIL, type ).query('
for $p in /p2/*
return
<Price PriceType = "{local-name($p)}">
{ data($p) }
</Price>
')
FROM Production.Product
WHERE ProductID = 520
FOR XML AUTO, TYPE;
En el ejemplo anterior se utiliza el método query() del tipo de datos xml para consultar el XML devuelto por la consulta FOR XML interna y construir el resultado esperado.
Este es el resultado:
<Production.Product ProductID="520">
<Price PriceType="ListPrice">133.3400</Price>
<Price PriceType="StandardCost">98.7700</Price>
</Production.Product>