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