SQL Server XQuery 学习笔记(二)

MSDN 查询词:XQuery 语言参考

一、 XQuery 基础知识

1、术语说明:

XSD:XML Schema 语言

原子类型:不可分割的类型,如 Schema 中内建的 string、integer 等

简单类型:原子类型、列表类型、联合类型合起来统称为简单类型,与复杂类型相对。

2、序列:由节点和原子值构成,序列中的项以逗号分隔。

空序列表示为 "()"

只包含一项的序列可视为原子值,如 (1) = 1,反之亦然。

在 SQL Server XQuery 的序列表达式中,序列必须是同类的,即或者是一个原子值序列,或者是一个节点序列,不能混搭。

3、命名空间声明:可以使用 WITH XMLNAMESPACES 声明,也可在 XML 数据类型相关的方法中使用 declare namespace 声明,若

两者声明的命名空间名称相同,后者会覆盖前者。如:

WITH XMLNAMESPACES ('http://someURI' as pd)

Select id, Catalog.query('declare namespace pd="http://otherURI";

        /pd:root/pd:type') From Product Where id = 9

4、预定义的命名空间,在 MSDN "序列和 QName (XQuery)" 一节中列出。

5、在 SQL Server XQuery 中,不支持当前日期和时间上下文函数:fn:current-date、fn:current-timet 和 fn:current-

dateTime。

6、原子化:提取项的类型化值的过程。

某些 XQuery 运算符依赖于隐式原子化,如算术运算符和比较运算符,当运用这一类型的运算符时,会隐式调用数据函数 data()

,首先检索节点的类型化值,并转换为原子值。例:

declare @x xml

set @x = '<root><int org="1.4">1</int><int org="2.8">3</int></root>'

select @x.query('sum(//int/@org)')       -- 返回:4.2

select @x.query('sum(//int)')            -- 返回:4

注意最后一句,类型为简单类型的元素也可以隐式原子化

7、布尔值:如果操作数是空序列或布尔 false,返回 false,否则返回 true。

Declare @x xml

Set @x = '<root><a>true</a></root>'

Select @x.query('if(//a[1]) then "true" else "false"')   --返回 "true"

但是

Select @x.query('if(data(//a[1])) then "true" else "false"')

会出现编译错误,因为 XQuery 中 if 只接受布尔值和节点集,而 data(//a[1]) 返回一个无类型的原子值(注意:不要以为该节

点下的文本为 "true",就会返回布尔值 true,但可以通过强制类型转换将其转换为布尔值,如 xs:Boolean(data((//a)[1])),

但是使用 xs:Boolean(data(//a[1])) 或 data(//a[1]) cast as xs:boolean? 则会导致转换错误),另一个解决的办法是定义一

个 Schema 与该 XML 文档关联,如

Create XML Schema Collection SC as '

<schema xmlns="http://www.w3.org/2001/XMLSchema">

        <element name="root">

              <complexType>

                    <sequence maxOccurs="unbounded">

                          <element name="a" type="Boolean" />

                    </sequence>

              </complexType>

        </element>

</schema>'

Go

declare @x xml(SC)

set @x = "<root><a>true</a></root>"

select @x.query('if(data((//a)[1])) then "true" else "false"')

注意:最后一句的判断条件 data((//a)[1]),有几点需要注意:

(1)   不可以省略为 (//a)[1],这将会变成一个节点选择,只要选择到相应的节点,返回值永远为 true。

(2)   不可以写为 data(//a[1]),//a[1] 其实会选择到一个节点集(如果多个元素包含 a 元素,会选择一系列的这些元素下的

第一个 a 元素)

(3)   也不可写为 data(/root/a[1]),原因同 (2),但可写为 data(/root[1]/a[1])。

 

最后还有一种很有趣的情形:

declare @x xml

set @x = ''

select @x.query('if(true) then "true" else "false"')

会返回什么?"true"?不对,是 "false",而且永远是 "false"。因为这里的 if 条件判断中,是把 true 当作一个元素选择来处

理的,即在 @x 中查找名称为 "true" 的元素,这肯定找不到,所以就永远返回 "false" 了。

那么改成 if("true") 行不行呢?不行,改成 if(1) 也不行。if 里的条件判断不会隐式转换类型,必须写成 if(xs:boolean

("true"))、if("true" cast as xs:boolean?) 或 if(true())。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值