Поддержка FOR XML для XML-данных

Если в предложении SELECT запроса FOR XML указан xml-столбец, значения столбца сопоставляются как элементы в возвращенном коде XML, независимо от того, указана ли директива ELEMENTS. XML-декларации в xml-столбце не сериализуются.

К примеру, следующий запрос извлекает данные о контактах заказчика, такие как столбцы ContactID, FirstName и LastName, а также телефонные номера из столбца AdditionalContactInfo типа 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

Поскольку запрос не содержит директивы ELEMENTS, значения столбцов возвращаются в виде атрибутов. Исключения составляют значения дополнительных сведений о контактах, полученные из xml-столбца. Эти значения возвращаются в виде элементов.

Промежуточный результат:

<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>
...

Если для XML-столбца, сформированного средствами языка XQuery, указывается псевдоним, этот псевдоним используется для добавления элемента «упаковщик» вокруг кода XML, сформированного с помощью XQuery. Так, в следующем запросе в качестве псевдонима столбца указывается MorePhoneNumbers:

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

Код XML, возвращаемый средствами XQuery, упаковывается в элемент <MorePhoneNumbers>, как показано в следующем частичном результирующем наборе:

<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>
...

В случае введения в запрос директивы ELEMENTS в полученном после его выполнения коде XML значения ContactID, LastName и FirstName будут возвращены в виде элементов.

Как видно из следующего примера, процедура обработки FOR XML не сериализует XML-декларации в XML-данных из столбца типа 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

Результат. В результате XML-декларация <?xml version="1.0" encoding="UTF-8" ?> является несериализованной.

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

Возвращение XML-данных из пользовательской функции

Запросы FOR XML можно использовать для возвращения XML-данных из пользовательской функции, которая возвращает один из следующих объектов:

  • таблицу с одним xml-столбцом;

  • экземпляр типа xml.

Так, следующая пользовательская функция возвращает таблицу с одним 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

Можно выполнять пользовательскую функцию и посылать запросы к возвращаемой ею таблице. В следующем примере XML-значение, возвращенное в результате опроса таблицы, присваивается xml-переменной.

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

Вот еще один пример пользовательской функции. Данная пользовательская функция возвращает экземпляр типа xml. В следующем примере пользовательская функция возвращает типизированный XML-экземпляр, поскольку здесь указано пространство имен схемы.

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

Возвращенный пользовательской функцией код XML может быть назначен xml-переменной следующим образом:

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