序列表达式 (XQuery)

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

示例 B

以下查询通过将四个不同长度的序列组合成一个序列,构造原子值序列。

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

示例 C

对 Contact 表中 xml 类型的 AdditionalContactInfo 列指定以下查询。此列存储附加联系信息,如一个或多个附加电话号码、寻呼机号码和地址。<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 />

若要仅检索具有属性 attrA 的 <a> 元素,可以在谓词中指定筛选器。筛选得到的序列将仅包含一个 <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>

下面的示例应用谓词筛选器。该表达式查找包含元素 <c> 的元素 <a> 和元素 <b>。

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 范围表达式。

  • 必须是同类序列。确切地说,序列中的所有项必须都是节点,或者都是原子值。这是通过静态检查来确定的。

  • 不支持使用 union、intersect 或 except 运算符组合节点序列。

请参阅

概念