XML與SQL SERVER2005 (六)

 

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 行受影響)

 

*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章