二、 XQuery 表达式
1、主表达式
(1) 与SQL语句一样,如果XQuery表达式中需要包含单引号,须转换为两个单引号。
(2) 可使用内置布尔函数 true() 或 false() 返回相应的bool值,如
Select @x.query('true()')
(3) 变量引用:以 $ 为前缀的 QNme,但不支持空间前缀,如
Select @x.query('for $i in /root return data($i)')
(4) 调用 XQuery 表达式外部的变量或数据库表中的普通列
l sql:variable 函数可引入表达式外部的变量,如:
Declare @x xml
Set @x = '<root><a>1</a><a>2</a><a>3</a></root>'
Declare @i int
Set @i = 2;
Select @x.query('//a[text()=sql:variable("@i")')
l sql:column 函数可引入数据库表中的非 XML 列值。假设有表 T_Area,表中有字段 AreaId 和 AreaName,则:
declare @x xml
set @x = ''
select @x.query('<Area><ID> sql:column("AreaId") </ID><Name> sql:column("AreaName") </Name></Area>') from T_Area
上面是转换为文本节点,转换为属性,如下:
Select @x.query('<Area ID="{sql:column("AreaID")}" Name="{sql:column("AreaName")}" />') from T_Area
转换为属性必须使用 {},转换为文本节点可用可不用。注意一下,这种转换与 For XML 的区别。
另外,在 sql:column 的参数中指定列名称时,与 SQL 一样,如果是多表联合查询,列名称有冲突时必须在列名称前加表名称或表别名。
2、路径表达式
(1) 其实就是 Xpath。强调一点:"/" 表示开始一个查找步骤,不要老是条件反射式的认为是子结点轴。
(2) 仅支持6种轴类型:child、descendant、parent、attribute、self、descendant-or-self,注意,反向轴只有 parent。
(3) 一个路径表达式分为三节:轴、节点测试、谓词。在节点测试中,"*"号可以匹配该轴下的主要元素,也可以仅匹配命名空间前缀及本地名称。如:
Declare @x xml
Set @x = '<greeting xmlns="ns1">
<salutation>Hello</salutation>
</greeting>
<greeting xmlns="ns2">
<salutation>welcome</salutation>
</greeting>
<farewell xmlns='ns2' />'
Select @x.query('//*:greeting')
Select @x.query('declare namespace ns="ns1"; /ns:*')
(4) 节点类型测试:
comment()、node()、processing-instruction()、text()
(5) 路径表达式中的谓词
l 注意因为括号而引起的计算顺序的不同,如
Select @x.query('/root/parent/child[1]')
Select @x.query('(/root/parent/child)[1]')
l 一个复杂谓词的示例
Declare @x xml
Set @x = '<People>
<Person><Name>Jim</Name><Age>32</Age></Person>
<Person><Name>Tom</Name><Age>13</Age></Person>
<Person><Name>Jeffery</Name><Age>45</Age></Person>
</People>'
Select @x.query('/People/Person[contains(Name[1], "J") and xs:integer(Age[1]) < 40)]/Name/text()')
在上面的表达式中,如果将 Name[1] 和 Age[1] 的谓词去掉,变成Name 和 Age,将会发生错误。
l 计算谓词的值
谓词的值只能为 xs:integer、xs:boolean 或 node*。
其实谓词的值最终都是 xs:boolean,因为 xs:integer 只是 position() = xs:integer 的简写,如 a[3] 与 a[position() = 3] 是一样的。而 node* 会隐式转换为 xs:boolean(空序列为 false,其它为 true)。
3、序列表达式
(1) 序列可以包含重复的值,嵌套的序列将会被折叠,如 (1, 4, (2, 1), 3, (4, 5)) 变成 (1, 4, 2, 1, 3, 4, 5)。
(2) 可以使用 FLOWR 对序列排序,如
Select @x.query('for $i in (1, 4, (2, 1), 3, (4, 5)) order by $i return $i')
(3) 序列包含的项数可以用 fn:count() 计算。
(4) 返回一个构造的序列
declare @x xml
set @x = '<root>
<class id="1">
<people>
<leader name="Jasic" age="22" />
<person name="Tom" age="24" />
<person name="Jack" age="18" />
</people>
</class>
<class id="2">
<people>
<leader name="Cookie" age="19" />
<person name="Sam" age="31" />
<person name="Tony" age="20" />
</people>
</class>
</root>'
select @x.query('for $a in //class return ($a//leader, $a//person)')
select @x.query('data((//leader/@name, //person/@name))')
(5) 生成子树的序列表达式
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')
select @x.query('(/a, /b)[c]')