Выражения последовательности (XQuery)
Применимо к:SQL Server
SQL Server поддерживает операторы XQuery, используемые для создания, фильтрации и объединения последовательности элементов. Элемент может быть атомарным значением или узлом.
Конструирование последовательностей
Оператор «запятая» позволяет сцеплять элементы в единую последовательность.
Последовательность может содержать повторяющиеся значения. Вложенные последовательности (последовательность в последовательности) всегда сворачиваются. Например, последовательность (1, 2, (3, 4, (5))) превращается в (1, 2, 3, 4, 5). Ниже приведены примеры конструирования последовательностей.
Пример A
Следующий запрос возвращает последовательность из пяти атомарных значений:
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. В этом столбце хранятся дополнительные контактные данные: адреса, номера телефонов и пейджеров. Номер <телефона>, <пейджер> и другие узлы могут отображаться в любом месте документа. Запрос создает последовательность, содержащую все дочерние <элементы телефона> узла контекста, а затем <дочерние элементы пейджера> . Обратите внимание на применение оператора последовательности в возвращаемом выражении ($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.