Выражения последовательности (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.Contact
WHERE ContactID=3

Результат:

<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>
Page only in case of emergencies.
</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.

См. также

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

Выражения языка XQuery