SQL Server XQuery 学习笔记(五)

 

4、算术表达式

(1)   算术运算符的参数必须为数字类型或 untypedAtomic。

(2)   不支持 idiv 运算符(idiv:整数除法,它返回一个整数值,忽略小数部分),可以通过以下方式模拟实现该运算符:

Select @x.query('xs:integer(2 div 3)')

5、比较表达式

(1)   常规比较运算符(=、!=、<、>、<=、>=)

常规比较运行符可用于:

l  两个序列的比较

l  序列与原子值的比较

l  两个原子值的比较

常规比较运算符只要其中任一项为真,则结果就为真,如

Select @x.query('(1, 2, 3) = (2, 5)') – 返回:true

Declare @y xml

Set @y = '<root><a>6</a><a>8</a></root>'

Select @y.query('//a < 7') – 返回:true

Select @y.query('//a > 7') – 返回:true

使用 = 运算符比较一个序列和一个原子值时,相当于测试该序列是否包含指定的原子值,如

Select @x.query('(1, 3, 4, 7) = 4')

在比较中,如果其中一个操作数是非类型化的,另一个是类型化的,则将非类型化的操作数转换为类型化操作数的类型。如果两个操作数都是非类型化的,则均转换为 xs:string。

(2)   值比较运算符(eq、ne(不等)、lt、gt、le(小于等于)、ge(大于等于))

值比较运算符只用于单一原子值,其操作数不能为序列(若空序列直接返回 false,单项序列会隐式调用 data() 函数获取类型化值,多项序列则会导致错误)。如:

Declare @x xml

Set @x = '<root><a>6</a><a>8</a></root>'

select @x.query('//a lt 7') – 错误

select @x.query('//a[1] lt 7') – 错误

select @x.query('(//a)[1] lt 7') – 返回:true

(3)   节点比较运算符(is)

测试两个节点是否是同一个节点,仅用于单一节点比较。如(接上例):

select @x.query('(//a)[1] is /root[1]/a[1]') – 返回:true

(4)   节点顺序比较运算符(<<、>>)

比较两个节点的先后关系,仅用于单一节点比较。

A << B,若节点 A 出现在节点 B 前面,返回 true,否则 false。

A >> B,若节点 A 出现在节点 B 后面,返回 true,否则 false。

6、XML 构造

所谓 XML 构造,其实就是通过 XQuery 构建一个新的 XML 格式文档。在 SQL Server XQuery 中,支持直接(direct)和(computed)构造,但因为计算构造时不允许动态计算节点的名称,所以两者在 SQL Server 中没有任何区别。

(1)   在 XQuery 中,使用 {} 可以明确指示大括号中的内容是查询表达式,而非常量。如:

declare @x xml

set @x = '<root><a>3</a><a>6</a></root>'

select @x.query('<NewRoot>{//a}</NewRoot>')

当然,也可以在大括号中使用函数:

select @x.query('<NewRoot>{data(//a)}</NewRoot>')

在些注一下 data() 和 string() 的区别:data() 可以接受一下序列,而返回的也是一个序列(原子值系列),而 string() 只能接受单一或空的序列,如下面的语句将会报错:

select @x.query('<NewRoot>{string(//a)}</NewRoot>') – 错误的

通过语句:

select @x.query('<NewRoot>{count(data(//a))}</NewRoot>')

可以很明显的看出 data() 返回的是一个序列。

若要在文本中使用 {},应使用转义 {{ 和 }}。

(2)   在大括号中包括完整的语句及嵌套大括号:

declare @x xml

set @x='

<root>

<step>This is step 1</step>

<step>This is step 2</step>

<step>This is step 3</step>

</root>'

 

select @x.query('<result>{for $i in /root/step return <s>{data($i)}</s>}</result>')

也可连续使用多个大括号:

select @x.query('<result>{string((//step)[1])} {string((//step)[1])}</result>')

注意:两个大括号间的空格会被忽略。

(3)   属性构造

属性可以接受原子值及原子值序列,如:

select @x.query('<result step="{(1, 2, 3)}" />')

这与下面的语句是等同的:

select @x.query('<result step="{1, 2, 3}" />')

都返回

<result step="1 2 3" />

在属性构造中传入节点时,会隐式调用 data(),如:

select @x.query('<result step="{//step}" />')

也可使用复杂的语句,如:

select @x.query('<result step="{for $i in //step where contains($i, "step") return $i}" />')

但是属性构造中不允许使用混合运算式,即要么使用单个大括号,要么直接使用常量值,不允许将常量和大括号混合使用,也不可以使用几个连续的大括号,如:

select @x.query('<result step="Step: {for $i in //step return $i}" />')

select @x.query('<result step="{string((//step)[1])}{string((//step)[2])}" />')

上述两个语句都是错误的

那如何解决类似于上述的需求呢?

l  为属性表达式构建一个原子值序列,如:

select @x.query('<result step="{"Step: ", data(//step)}" />')

注意这里的 data(//step) 必须显式使用 data() 函数,否则系统会认为这是一个混合序列,而导致错误。当然,也可以在两边加上小括号明确标示序列。

l  使用 concat() 函数连接字符串参数

select @x.query('<result step="{concat("Step: ", (//step)[1])}" />')

因为 concat 第二个参数是一个字符串,所以只能接受单个或空的序列。下面的例子也可明确的看到 data() 返回的是序列:

select @x.query('<result step="{concat("Step: ", (data(//step))[1])}" />')

(4)   添加命名空间

select @x.query('<root xmlns="a"><a>1</a></root>')

指定前缀:

select @x.query('<x:root xmlns:x="a"><a>1</a></x:root>')

为子元素指定相同的命名空间:

select @x.query('<x:root xmlns:x="a"><x:a>1</x:a></x:root>')

新构造的命名空间可以在查询中使用:

SELECT Instructions.query('

declare namespace AWMI="http://someURI";

        <FirstLocation xmlns:AWMI= "http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"  LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"

SetupHrs="{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >

           { /AWMI:root/AWMI:Location[1]/AWMI:step }

        </FirstLocation>

') as Result

FROM  Production.ProductModel

where ProductModelID=7

这里包含着一个命名空间优先级的问题,命名空间的优先级从低到高排列如下:外部声明的WITH XMLNAMESPACES(URI as xx) --> XQuery 表达式内部的 declare namespace xx=URI --> 属性构造中的 xmlns:xx=URI

声明默认命名空间可采用如下方式:

declare @x xml

set @x ='<x>5</x>'

select @x.query('declare default element namespace "a";

         <a><b xmlns=""/></a>')

(5)   计算构造 XML(仅支持 element、attribute、text)

declare @x xml

set @x=''

select @x.query('element root{

          element a {attribute type {"text"}, text {"test"} },

          element a {}

}')

返回值为:

<root><a type="text">test</a><a /></root>

对于空元素,名称后的大括号是必须的。

因为不支持动态生成节点名称,所以与直接构造相比,计算构造 XML 在 SQL Server XQuery中并没有什么优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值