Выражения последовательности (XQuery)

SQL Server поддерживает операторы XQuery, предназначенные для конструирования, фильтрации и комбинирования последовательностей элементов. Элемент может быть атомарным значением или узлом.

Конструирование последовательностей

Оператор «запятая» позволяет сцеплять элементы в единую последовательность.

Последовательность может содержать повторяющиеся значения. Вложенные последовательности (последовательность в последовательности) всегда сворачиваются. Например, последовательность (1, 2, (3, 4, (5))) превращается в (1, 2, 3, 4, 5). Ниже приведены примеры конструирования последовательностей.

Пример А

Следующий запрос возвращает последовательность из пяти атомарных значений:

declare @x xml;
set @x='';
select @x.query('(1,2,3,4,5)');
go
-- result 1 2 3 4 5

Следующий запрос возвращает последовательность из двух узлов:

-- sequence of 2 nodes
declare @x xml;
set @x='';
select @x.query('(<a/>, <b/>)');
go
-- result
<a />
<b />

Следующий запрос возвращает ошибку, так как конструируется последовательность из атомарных значений и узлов. Разнородные последовательности не поддерживаются.

declare @x xml;
set @x='';
select @x.query('(1, 2, <a/>, <b/>)');
go

Пример Б

Следующий запрос конструирует последовательность из атомарных значений, соединяя последовательности разной длины в единую последовательность.

declare @x xml;
set @x='';
select @x.query('(1,2),10,(),(4, 5, 6)');
go
-- result = 1 2 10 4 5 6

Сортировку последовательности можно произвести по FLOWR и ORDER BY:

declare @x xml;
set @x='';
select @x.query('for $i in ((1,2),10,(),(4, 5, 6))
                  order by $i
                  return $i');
go

Определить число элементов в последовательности позволяет функция fn:count().

declare @x xml;
set @x='';
select @x.query('count( (1,2,3,(),4) )');
go
-- result = 4

Пример В

Следующий запрос применяется к столбцу AdditionalContactInfo типа xml в таблице Contact. В этом столбце хранятся дополнительные контактные данные: адреса, номера телефонов и пейджеров. Узлы <telephoneNumber>, <pager> и другие могут находиться в любом месте документа. Запрос конструирует последовательность, которая содержит все дочерние элементы <telephoneNumber> узла контекста, а после них — дочерние элементы <pager>. Обратите внимание на применение оператора последовательности в возвращаемом выражении ($a//act:telephoneNumber, $a//act:pager).

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes' AS act,
 'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo' AS aci)

SELECT AdditionalContactInfo.query('
   for $a in /aci:AdditionalContactInfo 
   return ($a//act:telephoneNumber, $a//act:pager)
') As Result
FROM Person.Person
WHERE BusinessEntityID=291;

Результат:

<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">

<act:number>333-333-3333</act:number>

</act:telephoneNumber>

<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">

<act:number>333-333-3334</act:number>

</act:telephoneNumber>

<act:pager xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">

<act:number>999-555-1244</act:number>

<act:SpecialInstructions>

Страница только для случая чрезвычайных обстоятельств.

</act:SpecialInstructions>

</act:pager>

Фильтрация последовательностей

Можно отфильтровать возвращаемую последовательность по выражению, добавив предикат. Дополнительные сведения см. в разделе Выражения пути (XQuery). Например, следующий запрос возвращает последовательность, состоящую из трех узловых элементов <a>:

declare @x xml
set @x = '<root>
<a attrA="1">111</a>
<a></a>
<a></a>
</root>'
SELECT @x.query('/root/a')

Результат:

<a attrA="1">111</a>
<a />
<a />

Чтобы получить только элементы <a> с атрибутом attrA, укажите в предикате фильтр. Результирующая последовательность содержит только один элемент <a>.

declare @x xml
set @x = '<root>
<a attrA="1">111</a>
<a></a>
<a></a>
</root>'
SELECT @x.query('/root/a[@attrA]')

Результат:

<a attrA="1">111</a>

Дополнительные сведения об указании предикатов в выражениях пути см. в разделе Определение предикатов в шаге выражения пути.

Следующий пример производит построение выражения последовательности из поддеревьев, а затем применяет к последовательности фильтр.

declare @x xml
set @x = '
<a>
  <c>C under a</c>
</a>
<b>  
   <c>C under b</c>
</b>
<c>top level c</c>
<d></d>
'

Выражение в (/a, /b) конструирует последовательность с поддеревьями /a и /b, и из результирующей последовательности отфильтровывается элемент <c>.

SELECT @x.query('
  (/a, /b)/c
')

Результат:

<c>C under a</c>
<c>C under b</c>

Следующий пример показывает применение фильтра предиката. Выражение находит элементы <a> и <b>, содержащие элемент <c>.

declare @x xml
set @x = '
<a>
  <c>C under a</c>
</a>
<b>  
   <c>C under b</c>
</b>

<c>top level c</c>
<d></d>
'
SELECT @x.query('
  (/a, /b)[c]
')

Результат:

<a>
  <c>C under a</c>
</a>
<b>
  <c>C under b</c>
</b>

Ограничения реализации

Существуют следующие ограничения:

  • Не поддерживается XQuery-выражение RANGE.

  • Последовательности должны быть однородными. В частности, все элементы последовательности должны быть узлами или атомарными значениями. Эта проверка выполняется статически.

  • Не поддерживается комбинирование последовательностей узлов операторами union, intersect и except.

См. также

Основные понятия