Compatibilidad de FOR XML con el tipo de datos xml

Si una consulta FOR XML especifica una columna de tipo xml en la cláusula SELECT, los valores de columna se asignan como elementos en el XML devuelto, aunque no se especifique la directiva ELEMENTS. Las declaraciones XML en la columna de tipo xml no se serializan.

Por ejemplo, la consulta siguiente recupera información de contacto de clientes, como las columnas ContactID, FirstName y LastName, y los números de teléfono de la columna AdditionalContactInfo de tipo xml.

SELECT ContactID, FirstName, LastName, AdditionalContactInfo.query('
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
 //act:telephoneNumber/act:number
') AS PhoneNumber
FROM Person.Contact
FOR XML AUTO, TYPE

Como la consulta no especifica la directiva ELEMENTS, los valores de columna se devuelven como atributos, excepto en el caso de los valores de información de contacto adicional recuperados de la columna de tipo xml. Éstos se devuelven como elementos.

Éste es el resultado parcial:

<Contact ContactID="1" FirstName="Syed" LastName="Abbas">
    <act:number xmlns:act=
       "http://schemas.adventure-works.com/AdditionalContactTypes">
          111-111-1111</act:number>
    <act:number xmlns:act=
       "http://schemas.adventure-works.com/AdditionalContactTypes">
         112-111-1111</act:number>
</Contact>
<Contact ContactID="2" FirstName="Catherine" LastName="Abel">
    ...
</Contact>
...

Si se especifica un alias de columna para la columna XML generada por la consulta XQuery, se utiliza ese alias para agregar un elemento contenedor alrededor del XML generado. Por ejemplo, la consulta siguiente especifica MorePhoneNumbers como alias de columna:

SELECT ContactID, FirstName, LastName, AdditionalContactInfo.query('
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
 //act:telephoneNumber/act:number
') as MorePhoneNumbers
FROM Person.Contact
FOR XML AUTO, TYPE

El XML devuelto por la consulta XQuery se incluye dentro del elemento <MorePhoneNumbers>, como se muestra en el siguiente resultado parcial:

<Contact ContactID="1" FirstName="Syed" LastName="Abbas">
  <MorePhoneNumbers>
    <act:number xmlns:act="http://schemas.adventure-works.com/AdditionalContactTypes">111-111-1111</act:number>
    <act:number xmlns:act="http://schemas.adventure-works.com/AdditionalContactTypes">112-111-1111</act:number>
  </MorePhoneNumbers>
</Contact>
<Contact ContactID="2" FirstName="Catherine" LastName="Abel">
  <MorePhoneNumbers>
        ...
  </MorePhoneNumbers>
</Contact>
...

Si se especifica la directiva ELEMENTS en la consulta, se devolverán ContactID, LastName y FirstName como elementos en el XML resultante.

En el ejemplo siguiente se muestra cómo la lógica de procesamiento de FOR XML no serializa las declaraciones XML de los datos XML de una columna de tipo xml:

create table t(i int, x xml)
go
insert into t values(1, '<?xml version="1.0" encoding="UTF-8" ?>
                             <Root SomeID="10" />')
select i, x
from   t
for xml auto

Éste es el resultado. En el resultado, no se serializa la declaración XML <?xml version="1.0" encoding="UTF-8" ?>.

<root>
  <t i="1">
    <x>
      <Root SomeID="10" />
    </x>
  </t>
</root>

Devolver XML con una función definida por el usuario

Se pueden utilizar consultas FOR XML para obtener XML utilizando una función definida por el usuario que devuelva alguno de los siguientes resultados:

  • Una tabla con una sola columna de tipo xml

  • Una instancia del tipo xml

Por ejemplo, la siguiente función definida por el usuario devuelve una tabla con una sola columna de tipo xml:

CREATE FUNCTION MyUDF (@ProudctModelID int)
RETURNS @T TABLE
  (
     ProductDescription xml
  )
AS
BEGIN
  INSERT @T
     SELECT CatalogDescription.query('
declare namespace PD="https://www.adventure-works.com/schemas/products/description";
                    //PD:ProductDescription  ')
     FROM Production.ProductModel
     WHERE ProductModelID = @ProudctModelID
  RETURN
END

Se puede ejecutar la función definida por el usuario y consultar la tabla que devuelve. En este ejemplo, el XML devuelto al consultar la tabla se asigna a una variable de tipo xml.

declare @x xml
set @x = (SELECT * FROM MyUDF(19))
select @x

Éste es otro ejemplo de función definida por el usuario. Esta función definida por el usuario devuelve una instancia del tipo xml. En este ejemplo, la función definida por el usuario devuelve una instancia XML con tipo, porque se especifica el espacio de nombres del esquema.

drop function MyUDF4
go
CREATE FUNCTION MyUDF4 (@ProductModelID int) 
RETURNS xml ([Production].[ProductDescriptionSchemaCollection])
AS
BEGIN
  declare @x xml
  set @x =   ( SELECT CatalogDescription
          FROM Production.ProductModel
          WHERE ProductModelID = @ProductModelID )
  return @x
END

El resultado XML devuelto por la función definida por el usuario se puede asignar a una variable de tipo xml, como se indica a continuación:

declare @x xml
SELECT @x= dbo.MyUDF4 (19) 
select @x