XML与SQL SERVER2005 (六)

来源:互联网 发布:阿里云好代理吗 编辑:程序博客网 时间:2024/04/29 15:03

 

XMLSQL SERVER2005 ()

------------------------------------------------------------------------

-- Author : HappyFlyStone

-- Date   : 2009-09-11

-- Version: Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)

--       Apr 14 2006 01:12:25

--       Copyright (c) 1988-2005 Microsoft Corporation

--       Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

--  

--  本文探讨 SQL Server 2005 中内置的 XML 支持.

--  第六篇旨在对XQuery 的基础知识作简要说明。

--  本文来自happyflystone -CSDN博客,

--  转载请标明出处:http://blog.csdn.net/happyflystone

------------------------------------------------------------------------

 

 

 

      

 

Transact-SQL 支持用于查询 xml 数据类型的 XQuery 语言的子集。XQuery 是一种可以查询结构化或半结构化 XML 数据的语言。由于 SQL Server 2005 Database Engine 中提供 xml 数据类型支持,因此可以将文档存储在数据库中,然后使用 XQuery 进行查询。

XQuery 基于现有的 XPath 查询语言,并支持更好的迭代、更好的排序结果以及构造必需的 XML 的功能。XQuery XQuery 数据模型上运行。此模型是 XML 文档以及可能为类型化也可能为非类型化的 XQuery 结果的抽象概念。类型信息基于 W3C XML 架构语言所提供的类型。如果没有可用的类型化信息,XQuery 将按照非类型化处理数据。这与 XPath 1.0 版处理 XML 的方式相似。

若要查询 xml 类型的变量或列中存储的 XML 实例,可以使用 xml 数据类型方法(下表1,不作主要说明,这个以后单独再讲)。例如,可以声明一个 xml 类型的变量,然后使用 xml 数据类型的 query() 方法来查询此变量。

1

query()           XML实例进行查询

values()          XML实例检索SQL类型的值

exists()           非空性检测

modify()     对XMLMDL语句进行更新

nodes()           XML拆分形成多行

 

1XQuery

       先解释两个基本概念: Sequence 和 Qnames

      Sequence:序列,是XML中的一系列 XML 节点和 XSD 原子类型的实例组成。

Eg:

DECLARE @x xml

SET @x = ''

SELECT @x.query('<a>flystone</a>,<b>flystone</b>')

SELECT @x.query('"fly"," stone"')

SELECT @x.query('<a>{1+2}</a>')

 

/*

-------------------

<a>flystone</a><b>flystone</b>

 

(1 行受影响)

----------------

fly  stone

(1 行受影响)

--------------

<a>3</a>

(1 行受影响)

*/

Qname: XQuery 中的每个标识符都是一个 QName。QName 由一个命名空间前缀和一个本地名称组成。下面我们举一个不带前缀的例子:

DECLARE @x xml

SET @x = '<root><name>flystone1</name><name>flystone2</name></root>'

SELECT @x.query('//root/name')

 

/*

-----------------

<name>flystone1</name><name>flystone2</name>

 

(1 行受影响)

*/

//root/name 即是表达式,在这个表达式中,root name QNames

 

2、预定义命名空间

前缀            URI

xs              http://www.w3.org/2001/xmlxchema

xsi             http://www.w3.org/2001/xmlschema-instance

xdt             http://www.w3.org/2004/07/xpath-datetypes

fn              http://www.w3.org/2004/07/xpath-functions

              urn:schemas-microsoft-com:xml_sql

sqltypes       http://schemas.microsoft.com/sqlserver/2004/sqltypes

xml             http://www.w3.org/xml/1998/namespace

               http://schemas.imcrosoft.com/sqlserver/2004/soap

 

3、  分析和计算表达式

计算 Xquery的表达式分为两个阶段:静态上下文、动态上下文

a、静态上下文(查询编译阶段)

这个阶段主要完成如下过程:

l         边界空格

l         初始化前缀和命名空间绑定

l         可类型化列或变量导入XML 架构集合的组件

l         可用转换函数

b、动态上下文(查询执行阶段)

 

2、  原子化

原子化是提取项的类型化值的进程。可隐式或非隐式进行的。还是举几个例子吧

DECLARE @x xml

SET @x = '

<root>

    <name count="1">flystone1</name>

    <name count="5">flystone2</name>

</root>'

SELECT @x.query('sum(//root/name/@count)')

SELECT @x.query('sum(data(//root/name/@count))')

SET @x = '

<root>

    <name count="1">1</name>

    <name count="5">2</name>

</root>'

SELECT @x.query('sum(//root/name)')

SELECT @x.query('sum(data(//root/name))')

/*

-----------------

6

(1 行受影响)

-----------------

6

(1 行受影响)

-----------------

3

(1 行受影响)

-----------------

3

(1 行受影响)

*/

XQuery 函数属于 http://www.w3.org/2004/07/xpath-functions 命名空间。W3C 规范使用“fn:”命名空间前缀来说明这些函数。使用这些函数时,不必显式指定“fn:”命名空间前缀。由于这个原因,也为了提高可读性,此文档中通常不使用命名空间前缀。相关的函数我们可以查阅:

ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.zh-CHS/udb9/html/8df0877d-a03f-4ca9-b84e-908c4bb42b5e.htm

       我们仅用几个例子来说明一下,

ceiling()这个函数再熟悉不过了,取不小于当前数的最小整数(语句中有FLWOR,这个以后再说)。

DECLARE @x xml

SET @x = '

<root>

    <name count="1.9">flystone1</name>

    <name count="1.2">flystone2</name>

</root>'

SELECT @x.query('

for $i in //root/name

return

    <name count="{ceiling($i/@count)}">

        { $i/node() }

    </name>

')

 

/*

-----------------------------------------------------------------

<name count="2">flystone1</name><name count="2">flystone2</name>

 

(1 行受影响)

*/

   最后用两个SQL Server XQuery 扩展函数的个例子:

DECLARE @x table(id int,col xml)

insert @x select 1,'flystone1'

insert @x select 2,'flystone2'

 

SELECT id,col.query('

<col id="{sql:column("id")}">{/node()}

</col>') as col

from @x

 

/*

id          col

----------- -----------------

1           <col id="1">flystone1 <col/>

2           <col id="2">flystone2 <col/>

(2 行受影响)

*/

declare @i int,@x xml

set @i = 21000

set @x = '

<root>

    <name>flystone1</name>

    <name>flystone2</name>

</root>'

select @x.query('

for $i in //root/name

return

    <name postcode="{sql:variable("@i")}">

        {$i/node()}

    </name>

')

 

/*

----------------------------------------------------------

<name postcode="21000">flystone1</name><name postcode="21000">flystone2</name>

 

(1 行受影响)

*/

 

 

3、  有效的boolean

个人感觉也没什么复杂的,有时的点绕人而已,先来个简单的例子:

DECLARE @x XML

SET @x = '<b/>'

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

SELECT @x.query('if (/b[1]) then "true" else "false"')

/*

-----------

false

(1 行受影响)

 

-----------

true

(1 行受影响)

*/

再来一些有趣的:

DECLARE @x table(id int,col xml)

insert @x select 1,'<name sex=""><a><b/><c>flystone1</c></a></name>'

insert @x select 2,'<name sex=""><a>flystone2</a></name>'

 

SELECT id,col.query('

<col id="{sql:column("id")}">{/node()}

</col>') as col

from @x

where col.exist('/name[not(/name/a/*)]') =  0

/*

id          col

----------- --------------------------------------------------------

1 <col id="1"><name sex=""><a><b /><c>flystone1</c></a></name></col>

 

(1 行受影响)

*/

SELECT id,col.query('

<col id="{sql:column("id")}">{/node()}

</col>') as col

from @x

where col.exist('/name/a/b') =  0

/*

id          col

----------- ------------------------------------------

2           <col id="2"><name sex=""><a>flystone2</a></name></col>

 

(1 行受影响)

*/

 

 

SELECT id,col.query('

<col id="{sql:column("id")}">{/node()}

</col>') as col

from @x

where col.value('(name/@sex)[1]','varchar(4)')=''

/*

id          col

----------- ---------------------------------------

1 <col id="1"><name sex=""><a><b /><c>flystone1</c></a></name></col>

 

(1 行受影响)

*/

 

4、  类型系统

XQuery 对于架构类型是强类型语言,对于非类型化的数据是弱类型语言。预定义的 XQuery 类型包括:

http://www.w3.org/2001/XMLSchema 命名空间中 XML 架构的内置类型。

http://www.w3.org/2004/07/xpath-datatypes 命名空间中定义的类型。

被查询的 XML 是非类型化时元素节点的静态类型和动态类型都是 xdt:untyped,属性值的类型是 xdt:untypedAtomic 。下面我们分别就非类型化和类型化用使用 instance of 来验证返回的结果搞几个例子:

CREATE XML SCHEMA COLLECTION SC AS N'

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

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

</schema>'

go

 

declare @x xml

set @x='<a>20</a>'

select @x.query( 'data(/a[1]) instance of xdt:untypedAtomic' )

--error,这种写法是错误 ,query()方法结果是非类型化的,因此返回值是xdt:untypeAtomic,data(/a[1])是一个元素经,所以instance of 表达式得使用元素测试来验证类型

--select @x.query( 'data(/a[1]) instance of xdt:untyped' )

-- success

select @x.query( '/a[1] instance of element(a, xdt:untyped?)')

DECLARE @y xml(SC)

SET @y='<a>5</a>'

select @y.query( 'data(/a[1]) instance of xs:integer' )

DROP XML SCHEMA COLLECTION SC

/*

------------------

true

(1 行受影响)

------------------

true

(1 行受影响)

------------------

true

(1 行受影响)

*/

 

5、  静态错误、动态错误

这个似乎有点有趣,看下面这个

DECLARE @x xml

SET @x='<a>Hello</a>'

SELECT @x.query('xs:double(/a[1])')

SET @x=N'<root xmlns:myNS="test">

 <a>100</a>

 <b>200</b>

 <c>Hello</c>

</root>'

SELECT @x.query('avg(//*)')

 

/*

---------------

 

(1 行受影响)

----------------

150

 

(1 行受影响)

*/

6、  XQuery 中的注释

使用(::)分隔符在 XQuery 中添加注释。

declare @x xml

set @x=''

SELECT @x.query('

(: simple query to construct an element :)

<root id="10" />

')

/*

-----------------

<root id="10" />

 

(1 行受影响)

 

*/

 

原创粉丝点击