XML
已成為近來最熱門的Web技術
它是SQL Server
中的重要部分
本文將綜合七條SQL Server
中最重要的XML綜合特性組成XML之七種兵器
兵器之一
FOR XML
在SQL Server
中
標准的T
SQL SELECT語句包括FOR XML子句
它以XML文檔形式返回一個查詢結果
新的FOR XML子句有三種模式——RAW
AUTO
和EXPLICIT
每個都能對XML文檔格式提供附加標准的控制
下面首先介紹
FOR XML
的使用方法
為了從SQL Server提取XML格式的數據
T
SQL中加入了一個FOR XML命令
在查詢命令中使用FOR XML命令使得查詢結果以XML格式出現
FOR XML命令有三種模式
RAW
AUTO和EXPLICIT
圖
所顯示的SQL命令訪問SQL Server提供的Pubs示例數據庫
有關Pubs數據庫的更多信息
請參見MSDN說明
如果我們依次指定該SQL命令的模式為三種允許的模式之一
就可以得到各種模式所支持的不同XML輸出
SELECT store
stor_id as Id
stor_name as Name
sale
ord_num as OrderNo
sale
qty as Qty
FROM stores store inner join
sales sale on store
stor_id = sale
stor_id
ORDER BY stor_name
FOR XML <模式>
該查詢命令所生成的結果包含所有銷售記錄及其對應的商店
結果以商店名稱的字母升序排列
查詢的最後加上了FOR XML命令以及具體的模式
比如FOR XML RAW
理想情況下SQL命令所生成的XML文檔應具有如下結構 <Stores>
<Store Id=&single;&single; Name=&single;&single;>
</Sale OrderNo=&single;&single; Qty=&single;&single;>
</Store>
</Stores>
下面我們來看看具體的處理方法
RAW模式 下面是指定RAW模式時結果XML文檔的一個片斷
查詢結果集中每一個記錄包含唯一的元素<row>
由於我們無法控制元素名字和文檔結構
因此這種模式不是很有用
RAW模式所生成的文檔結構與我們所希望的不符
而且它的用途也非常有限
AUTO模式 下面是指定AUTO模式時結果文檔的一個片斷
可以看到
<Stroe>和<Sale>兩個元素是父
子關系
形成了我們所希望的層次結構
這種節點關系由查詢中表的聲明次序決定
後聲明的表成為前聲明表的孩子
我們可以看出查詢命令所指定的別名決定了XML文檔中的名字
根據這一點
我們可以控制XML文檔元素
屬性的名字
使得這些名字符合我們所要求的命名慣例
可見AUTO模式能夠創建出我們所需要的XML文檔
不過它存在以下缺點
雖然可以得到層次結構
但這種層次結構是線性的
即每個父節點只能有一個子節點
反之亦然
通過別名指定元素名字不太方便
而且有時候會影響查詢命令本身的可讀性
無法在文檔中同時生成元素和屬性
要麼全部是元素(通過ELEMENTS關鍵詞指定)
要麼全部是屬性(默認)
EXPLICIT模式解決了上述不足
EXPLICIT模式
EXPLICIT模式比較復雜
我們將用另外一種方法來表達所顯示的查詢
這種方法使得我們能夠完全地控制查詢所生成的XML文檔
首先我們將介紹如何改用EXPLICIT模式編寫圖
所顯示的查詢
然後看看這種方法如何賦予我們遠遠超過AUTO模式的能力
商店數據
SELECT
as Tag
NULL as Parent
s
stor_id as [store!
!Id]
s
stor_name as [store!
!Name]
NULL as[sale!
!OrderNo]
NULL as [sale!
!Qty]
FROM stores s
UNION ALL
銷售數據
SELECT
s
stor_id
s
stor_name
sa
ord_num
sa
qty
FROM stores s
sales sa
WHERE s
stor_id = sa
stor_id
ORDER BY [store!
!name]
FOR XML EXPLICIT
這個查詢初看起來有點復雜
其實它只是把不同的數據集(即這裡的Store和Sale)分解到了獨立的SELECT語句裡
然後再用UNION ALL操作符連結成一個查詢
我們之所以要把查詢寫成上面的形式
是為了讓查詢結果不僅包含XML文檔所描述的數據
而且還包含描述XML文檔結構的元數據
上述查詢所生成的表稱為Universal表
sqlxml
dll生成XML文檔時需要這種格式
Universal表對於編寫代碼的人來說是透明的
但了解這個表還是很有意義的
它將有助於代碼的開發和調試
下面是Universal表的一個例子
Tag Parent store!
!id store!
!name sale!
!orderno sale!
!qty
NULL
Barnum&single;s NULL NULL
Barnum&single;s A
Barnum&single;s QA
NULL
Bookbeat NULL NULL
Bookbeat
LL
Universal表和EXPLICIT模式查詢的元數據部分都以紅色表示
黑色表示數據
比較查詢和表就可以找出sqlxml
dll生成XML文檔所需要的元素
我們來仔細地分析一下它們描述的是什麼
Tag和Parent列是XML文檔層次結構方面的信息
我們可以認為每個SELECT語句代表了一個XML節點
而Tag和Parent列讓我們指定節點在文檔層次結構中的位置
如果在第二個SELECT語句中指定Tag為
指定Parent為
就表示為這些數據加上了一個值為
的標簽
而這些數據的父親是那些標簽為
的數據(即第一個SELECT語句)
這就使得我們能夠構造出<Store>和<Sale>之間的父
子關系
而且正如你可能猜想到的
它使得我們可以生成任意合法的XML文檔結構
注意第一個SELECT命令的parent列設置成了NULL
這表示<Store>元素處於最頂層的位置
以黑色表示的數據將成為節點的屬性或元素
例如
Store_ID就通過列名提供了這方面的信息
列名字中的
!
是分隔符
總共可分成四項(四個參數)
其中第四個參數是可選的
這些參數描述的是
第一個參數描述該列所屬元素的名字
在這裡是<Store>元素
第二個是標簽編號
它指定了該列信息在XML樹形結構中所處位置
第三個參數指定XML文檔內的屬性或元素名字
在這裡名字指定為id
數據列默認被創建為參數
所指定節點的屬性
即id將成為<Store>節點的屬性
如果要指定id是<Store>的一個子元素
我們可以使用第四個可選的參數
這個參數的一個作用就是讓我們把該項指定為元素
例如store!
!id!element
由於使用了UNION ALL操作符來連結SELECT語句
為了保證SQL查詢的合法性
所有SELECT語句的選擇結果必須具有相同數量的列
我們使用NULL關鍵詞來補足SELECT語句
從而避免了重復數據
通過EXPLICIT模式查詢所生成的XML文檔和通過AUTO模式生成的完全相同
那麼為什麼要創建EXPLICIT模式查詢呢?
假設現在有人要求在XML文檔中包含商店的打折信息
查看Pubs數據庫
我們得知每個商店都可以有
到n范圍內的折扣率
因此
一種合理的方法是在<Store>元素下面加上子元素<Discount>
這樣我們就得到如下XML文檔結構
<STORES>
<STORE Id=&single;&single; Name=&single;&single;>
<DISCOUNT Type=&single;&single; LowQty=&single;&single; HighQty=&single;&single;>
<AMOUNT></AMOUNT>
</DISCOUNT>
<SALE OrdNo=&single;&single; Qty=&single;&single;>
</SALE>
</STORE>
</STORES>
這裡的改動包括
要在<Sale>元素所在的層次增加一個XML元素<Discount>
即<Discount>是<Stroe>的子元素
Amount嵌套在<Discount>裡面
但不應該是<Discount>元素的屬性
在AUTO模式中是不可能實現這些改動的
下面是創建這個新XML文檔的EXPLICIT模式查詢
SELECT
as Tag
NULL as Parent
s
stor_id as [Store!
!id]
s
stor_name as [Store!
!name]
NULL as [Sale!
!orderno]
NULL as [Sale!
!
ty]
NULL as [Discount!
!type]
NULL as [Discount!
!lowqty]
NULL as [Discount!
!highqty]
NULL as [Discount!
!amount!element]
FROM stores s
UNION ALL
SELECT
s
stor_id
s
stor_name
sa
ord_num
sa
qty
NULL
NULL
NULL
NULL
FROM stores s
sales sa
WHERE s
stor_id = sa
stor_id
UNION ALL
SELECT
NULL
s
stor_name
NULL
NULL
d
discounttype
d
lowqty
d
highqty
d
discount
FROM stores s
discounts d
WHERE s
stor_id = d
stor_id
ORDER BY [store!
!name]
For XML EXPLICIT
為了創建圖
A所顯示的EXPLICIT模式查詢
我們對圖
的查詢進行了如下修改
增加了第三個子查詢提取折扣數據
通過Tag列聲明這些數據的標簽值為
通過指定Parent列為
將折扣數據設置成<Store>元素的子元素
From:http://tw.wingwit.com/Article/program/SQLServer/201311/22115.html