Поделиться через


Вложенные запросы FOR XML

В SQL Server 2000 предложение FOR XML можно указать только на верхнем уровне запроса SELECT. Результирующий XML в основном возвращается клиенту для дальнейшей обработки. Однако, начиная с версии SQL Server 2005, тип данных xml и директива TYPE в запросах FOR XML позволяют дополнительно обработать на сервере XML-документы, возвращаемые запросами FOR XML.

Обработка переменных типа XML

Результат запроса FOR XML можно присвоить переменной типа xml или воспользоваться языком XQuery, чтобы выполнить к нему запрос, после чего присвоить полученный результат переменной типа xml для дополнительной обработки.

USE AdventureWorks2008R2;
GO
DECLARE @x xml;
SET @x=(SELECT ProductModelID, Name
        FROM Production.ProductModel
        WHERE ProductModelID=122 OR ProductModelID=119
        FOR XML RAW, TYPE);
SELECT @x;

— Результат

--<row ProductModelID="122" Name="All-Purpose Bike Stand" />

--<row ProductModelID="119" Name="Bike Wash" />

XML-данные, возвращаемые в переменной @x, можно дополнительно обработать с применением методов типа данных xml. Например, с помощью метода value() можно получить значение атрибута ProductModelID.

DECLARE @i int;
SET @i = (SELECT @x.value('/row[1]/@ProductModelID[1]', 'int'));
SELECT @i;

В следующем примере результат запроса FOR XML возвращается в виде типа данных xml, так как в предложении FOR XML указана директива TYPE.

SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=119 OR ProductModelID=122
FOR XML RAW, TYPE,ROOT('myRoot');

Результат:

<myRoot>

<row ProductModelID="122" Name="All-Purpose Bike Stand" />

<row ProductModelID="119" Name="Bike Wash" />

</myRoot>

Поскольку результат имеет тип xml, непосредственно к нему можно применить один из методов типа данных xml, как показано в следующем запросе. В запросе метод query() (тип данных xml) используется для получения первого дочернего элемента <row> элемента <myRoot>.

SELECT  (SELECT ProductModelID, Name
         FROM Production.ProductModel
         WHERE ProductModelID=119 OR ProductModelID=122
         FOR XML RAW, TYPE,ROOT('myRoot')).query('/myRoot[1]/row[1]');

Результат:

<row ProductModelID="122" Name="All-Purpose Bike Stand" />

Передача результатов внутреннего запроса FOR XML внешним запросам в виде экземпляров типа xml

Можно создать вложенные запросы FOR XML, в которых результат внутреннего запроса возвращает внешнему запросу данные типа xml. Например:

SELECT Col1, 
       Col2, 
       ( SELECT Col3, Col4 
        FROM  T2
        WHERE T2.Col = T1.Col
        ...
        FOR XML AUTO, TYPE )
FROM T1
WHERE ...
FOR XML AUTO, TYPE;

В приведенном запросе обратите внимание на следующие моменты.

  • XML-данные, сформированные внутренним запросом FOR XML, добавляются к XML-результату внешнего запроса FOR XML.

  • Во внутреннем запросе указана директива TYPE. Таким образом, возвращаемые внутренним запросом XML-данные имеют тип xml. Если директива TYPE не указана, внутренний запрос FOR XML возвращает результат типа nvarchar(max) и XML-данные преобразуются в сущности.

Управление формой результирующих XML-данных

Вложенные запросы FOR XML предоставляют больше возможностей управления формой результирующих XML-данных. В SQL Server 2000 запросы режимов RAW и AUTO по умолчанию формируют атрибутивную модель XML-данных. Например:

USE AdventureWorks2008R2;
GO
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML RAW;

Результат является атрибутивным:

<row ProductModelID="122" Name="All-Purpose Bike Stand" />

<row ProductModelID="119" Name="Bike Wash" />

Кроме того, получить все XML-данные в элементной форме можно при помощи директивы ELEMENTS. Например:

SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML RAW, ELEMENTS ;

Результат является элементным:

<строка>

<ProductModelID>122</ProductModelID>

<Name>All-Purpose Bike Stand</Name>

</row>

<строка>

<ProductModelID>119</ProductModelID>

<Name>Bike Wash</Name>

</row>

Таким образом, в SQL Server 2000 для результата запросов необходимо выбрать атрибутивную или элементную модель XML. Начиная с версии SQL Server 2005, при помощи вложенных запросов FOR XML можно конструировать XML-данные, сочетающие в себе атрибутивную и элементную модели.

Дополнительные сведения об указании как атрибутивной, так и элементной моделей XML-данных при помощи вложенных запросов FOR XML см. в разделах Сравнение запросов FOR XML и вложенных запросов FOR XML и Формирование XML-кода с вложенными запросами FOR XML.

В SQL Server 2000 узлы с общим родителем можно создавать только с помощью запросов в режиме EXPLICIT. Однако пользоваться этим способом не всегда удобно. Начиная с версии SQL Server 2005, с помощью вложенных запросов FOR XML в режиме AUTO можно формировать XML-иерархии, содержащие одноуровневые элементы. Дополнительные сведения см. в разделе Формирование одноуровневых элементов с помощью вложенного запроса в режиме AUTO.

Независимо от используемого режима вложенные запросы FOR XML предоставляют больший контроль при описании формата результирующих XML-данных. Их можно использовать вместо запросов в режиме EXPLICIT.

Примеры

В следующих разделах содержатся примеры использования запросов FOR XML.