級別: 初級
陳 力
(chenli44@yeah.net), 北京師范大學(xué)信息管理專業(yè)研究生
張 大為 (zhangdaw@cn.ibm.com), 軟件工程師
2006 年 9 月 21 日
摘要:本文將介紹 DB2 提供的一些基本 XML 函數(shù),并結(jié)合一個簡單的實例,重點介紹如何利用 DB2 提供的 XML 函數(shù)以視圖或查詢的形式靈活的實現(xiàn) XML 文檔的構(gòu)造和發(fā)布。
DB2 提供了豐富的功能用以發(fā)布 XML 格式的數(shù)據(jù),這種功能包括了 DB2 內(nèi)置的 XML 函數(shù)以及 XML extender 提供的功能(包括了發(fā)布、解析、檢索、存儲等多種功能)。對 XML 文檔的支持,使得利用現(xiàn)有的 DB2 數(shù)據(jù)庫,就能夠方便的實現(xiàn)系統(tǒng)或者數(shù)據(jù)的整合。
本文讀者定位為具有一定的 DB2 開發(fā)經(jīng)驗,同時對 XML 語言的格式、schema 定義、命名空間等有基本的理解。
本文將介紹 DB2 提供的一些基本 XML 函數(shù),并結(jié)合一個簡單的實例,重點介紹如何利用 DB2 提供的 XML 函數(shù)以視圖或查詢的形式靈活的實現(xiàn) XML 文檔的構(gòu)造和發(fā)布。同時文中還將介紹利用作者編制的一個工具,根據(jù)目標(biāo) XML 的樣例文檔生成相應(yīng)的包含 XML 函數(shù)的查詢框架,以輔助開發(fā)較為復(fù)雜的 XML 文檔結(jié)構(gòu)的 SQL 語句。
以 DB2 的 XML 函數(shù)為基礎(chǔ)的 SQL 語句支持 XML 語言的絕大部分特征,可以簡單而直觀地實現(xiàn)從關(guān)系型數(shù)據(jù)模型到 XML 的樹狀結(jié)構(gòu)的轉(zhuǎn)換,其靈活性接近于手工書寫 XML 文檔,同時,只要利用適當(dāng)?shù)姆椒ê凸ぞ?,就可以在不增加開發(fā)復(fù)雜度的基礎(chǔ)上大大降低開發(fā)的工作量。
1.DB2 XML 查詢/視圖及 XML 函數(shù)簡介
利用 XML 函數(shù)我們可以方便的構(gòu)建 XML 查詢或視圖,利用這些函數(shù)發(fā)布 XML 的整個過程與開發(fā)和使用傳統(tǒng)的查詢與視圖并沒有本質(zhì)的區(qū)別。XML 查詢不需要依賴于復(fù)雜的發(fā)布程序和軟件平臺,即使只有 DB2 命令行客戶端,我們也能夠連接數(shù)據(jù)庫發(fā)布 XML 文檔??梢娎眠@種方式進(jìn)行 XML 發(fā)布具有很廣泛的應(yīng)用范圍,能夠適應(yīng)從高級語言開發(fā)的網(wǎng)絡(luò)程序到簡單的 Shell 腳本這樣不同級別實現(xiàn)的要求,而且特別有利于簡單直接的解決方案。這給我們以 DB2 數(shù)據(jù)庫為基礎(chǔ)實現(xiàn)異構(gòu)數(shù)據(jù)系統(tǒng)的整合與互動功能提供了一個簡便易行的方法。
DB2 UDB 8.2 直接提供了 7 種 SQL/XML 函數(shù),以及與這些 XML 語法成分對應(yīng)的 XML 數(shù)據(jù)類型。
XML函數(shù)列表:
XMLSERIALIZE
XMLELEMENT
XMLATTRIBUTES
XMLNAMESPACES
XMLFOREST
XMLCONCAT
XMLAGG
除了 XMLSERIALIZE 之外,其他六個函數(shù)均返回 XML 數(shù)據(jù)類型,包括了元素、屬性、命名空間、節(jié)點集。利用這些函數(shù)提供的 XML 成分,我們可以構(gòu)造出任意指定的 XML 文檔結(jié)構(gòu)。DB2 的 XML 函數(shù)已經(jīng)提供了足夠的功能,可以認(rèn)為只要設(shè)計人員能從業(yè)務(wù)邏輯上實現(xiàn)從關(guān)系數(shù)據(jù)模型到 XML 文檔樹狀結(jié)構(gòu)的映射關(guān)系的設(shè)計,開發(fā)人員就能夠利用這些基本函數(shù)直接實現(xiàn) XML 文檔的生成。
我們在這里使用簡單的示例對上述 XML 函數(shù)一一進(jìn)行介紹。我們在本地數(shù)據(jù)庫中創(chuàng)建了一個簡單的 Contact 表,并且插入了幾條數(shù)據(jù),作為示例基礎(chǔ):
SELECT cust_num, f_name, l_name, email, cnt_num FROM contact

XMLSERIALIZE:
XMLSERIALIZE 函數(shù)是一個特殊的函數(shù),并不產(chǎn)生 XML 文檔的一部分,而是用于將其他函數(shù)產(chǎn)生的 XML 數(shù)據(jù)類型轉(zhuǎn)化為其他的常見數(shù)據(jù)類型,如 CHAR、VARCHAR 和 CLOB 等。由于 XML 數(shù)據(jù)類型不能直接存儲到數(shù)據(jù)庫中,也不能直接輸出,通常都需要使用 XMLSERIALIZE 函數(shù)進(jìn)行轉(zhuǎn)換,后面的示例也都會使用到它。
XMLELEMENT:
XMLELEMENT 是最基礎(chǔ)的 XML 函數(shù),用于構(gòu)建 XML 元素節(jié)點,這個函數(shù)接受元素名稱和元素內(nèi)容兩個必選參數(shù),另外還可以接受 XML 屬性和命名空間參數(shù)。元素內(nèi)容可以是 CHAR、VARCHAR、INT 等基本數(shù)據(jù)類型,也可以是 XML 元素數(shù)據(jù)類型,允許 XMLELEMENT 函數(shù)的嵌套。
清單1
|

XMLATTRIBUTES與XMLNAMESPACES:
XMLATTRIBUTES與XMLNAMESPACES函數(shù)的使用方法非常類似,當(dāng)前者作為參數(shù)傳給XMLELMENT函數(shù)后可以為該元素添加屬性,而后者則可以向元素中添加命名空間以及命名空間前綴的聲明,多個屬性/命名空間可以通過一個XMLATTRIBUTES或XMLNAMESPACES函數(shù)一次性添加。
清單2
|

XMLFOREST與XMLCONCAT:
XMLFOREST與XMLCONCAT的功能類似,用以生成一組并列的XML元素節(jié)點使之具有相同的內(nèi)部XML數(shù)據(jù)類型,如<elem1>…</elem1><elem2>…</elem2><elem3>…</elem3>這樣的形式。XMLFOREST用于根據(jù)輸入的多個一般類型值參數(shù)生成簡單的文本節(jié)點"森林",XMLCONCAT接受的參數(shù)只能是XML數(shù)據(jù)類型,可以用于將許多復(fù)雜的元素節(jié)點組合在一起形成并列的節(jié)點結(jié)構(gòu)。
清單3 XMLFOREST與XMLCONCAT對比
|

|

這兩個函數(shù)雖然結(jié)果形式類似,但是其功能卻是不同的。XMLFOREST 只能生成簡單值元素的"森林",不能靈活的設(shè)置這些值元素的屬性和命名空間聲明等,但是它語法非常簡單,非常適合用在處理多個葉子值節(jié)點并列出現(xiàn)的情況。而 XMLCONCAT 能將多個復(fù)雜的 XML 元素節(jié)點形成并列的節(jié)點結(jié)構(gòu)。XMLSERIALIZE 只能接受一個 XML 數(shù)據(jù)類型的參數(shù),在上述例子中 XMLCONCAT 用來將多個 XML 元素形成并列節(jié)點結(jié)構(gòu)并且返回一個相同的 XML 數(shù)據(jù)類型傳給 XMLSERIALIZE,如果不使用 XMLCONCAT 將無法成功調(diào)用 XMLSERIALIZE。
XMLAGG:
XMLAGG 是 XML 函數(shù)中唯一的聚集函數(shù),XMLAGG 函數(shù)可以將若干條記錄中的列值按照 XML 結(jié)構(gòu)的定義聚集成為"森林"結(jié)構(gòu),合成到一條記錄中。XMLAGG 為我們根據(jù)數(shù)據(jù)實現(xiàn)動態(tài)樹狀結(jié)構(gòu)提供了基礎(chǔ),是映射關(guān)系數(shù)據(jù)到 XML 文檔的重要工具之一。通過 WITH 語句我們還能實現(xiàn)分層聚集、分列聚集這樣的功能,但復(fù)雜的查詢中很可能會產(chǎn)生性能問題。
清單4.1 XMLAGG一般情況
|

先按客戶分組再按客戶聯(lián)系人所在城市分組聚集:
清單4.2 XMLAGG 嵌套多層聚集
|

加入另一示例表 sold_product,包含客戶與產(chǎn)品的聯(lián)系,在 XML 文檔中在每個客戶節(jié)點下面包含該客戶的所有產(chǎn)品信息與所有聯(lián)系人信息,即將每個客戶的產(chǎn)品信息和聯(lián)系人信息進(jìn)行并列聚集:
清單4.3 XMLAGG 不同列的聚集
|

![]() ![]() |
![]()
|
2.DB2 示例數(shù)據(jù)準(zhǔn)備與 XML 文檔設(shè)計
在這里我們將使用一個完整的示例,來展示如何應(yīng)用這些 XML 函數(shù)開發(fā) XML 查詢和試圖的基本過程。我們所設(shè)計的示例希望使用大部分 XML 函數(shù),展示典型應(yīng)用場景。
在進(jìn)行 XML 視圖的開發(fā)之前,我們在前面 contact 示例表的基礎(chǔ)上,準(zhǔn)備好兩個關(guān)聯(lián)的數(shù)據(jù)表 customer 表與 contact 表,前者與后者是一對多的關(guān)系,即一條 customer 記錄可以擁有多個聯(lián)系人記錄。
清單5:示例表及數(shù)據(jù)樣例
Customer表

Contact表

我們要將 customer 表中的每一位顧客的信息連同與之相聯(lián)系的若干 contact 記錄通過一個 XML 文檔發(fā)布,在我們需要實現(xiàn)的 XML 文檔結(jié)構(gòu)中必然會出現(xiàn)一個 Customer 元素中包含若干個 contact 元素的樹狀結(jié)構(gòu),如圖 1 所示。
圖1

在通常的開發(fā)過程中,我們一般將會被要求根據(jù)已定義好的 XSD 文檔,來實現(xiàn)指定格式的 XML 文檔發(fā)布。但 XSD 定義文件并不是必需的,它只是嚴(yán)密地告訴我們目標(biāo) XML 文檔的結(jié)構(gòu)。實際上編寫 XML 查詢或視圖時,更應(yīng)該重視 XML 文檔樣例。因為有很多時候,設(shè)計過程可能只提供 XML 文檔樣例,不過這已經(jīng)足夠了。
在這里為了將示例的目標(biāo) XML 文檔準(zhǔn)確的表達(dá)出來,我們也使用 XSD 對其進(jìn)行定義,編寫出定義文件 customer.xsd,如圖2所示。
圖2 XSD(參見下載中的customer.xsd文件)

customer.xsd 文件中定義了在發(fā)布數(shù)據(jù)客戶-聯(lián)系人信息中所需的若干數(shù)據(jù)類型和子結(jié)構(gòu)類型,如 LocationType、EmailType、CityType 等,對基本的數(shù)據(jù)庫類型進(jìn)行了結(jié)構(gòu)化封裝,并且規(guī)定了 XML 文檔的元素層次結(jié)構(gòu)。這里根元素為 CustomerInfo,目標(biāo)命名空間定義為:"http://www.ibm.com/schemas/SimpleXMLDemo",這個定義文件所形成的 XML 文檔結(jié)構(gòu)如圖 3 所示。
圖3 CustomerInfo 文檔結(jié)構(gòu)

圖3中紅色方框所示的部分說明在一個 CustomerInfo 文檔中 Contacts 元素節(jié)點下將包含一個或者多個 Contact 子元素,每一個 Contact 子元素包含一位聯(lián)系人的信息。
現(xiàn)在的 XSD 定義已經(jīng)涉及到了命名空間的聲明,但在此文檔中所有的元素及數(shù)據(jù)類型都屬于"http://www.ibm.com/schemas/SimpleXMLDemo"這一命名空間。一個更加普遍的情況是,XML 文件的定義使用了來自不同命名空間的成分,這也是 XML 可重用性的體現(xiàn)。為了模擬這種效果,我們將與 contact 及其子元素有關(guān)的所有定義從 customer.xsd 中分離出來放入另一個獨立的 XSD 文件 contact.xsd 中去,并且給該文件的命名空間設(shè)置為"http://www.ibm.com/schemas/ContactDemo"
圖4 分離后文檔定義結(jié)構(gòu)(參見下載中的contact.xsd文件)

customer.xsd(contact命名空間前綴聲明為cnt):

按照 customer.xsd 文件的定義,我們手工生成一個樣本 XML 文檔 sample.xml,文檔中僅包含一個 Contact 子節(jié)點。這樣一個完整的 XML 文檔樣例,在實際的 XML 查詢編寫過程中會起到非常重要的作用,可以給開發(fā)人員一個直觀的模板。此外,XML 高度的結(jié)構(gòu)化特點也使利用軟件工具來處理變得非常方便。
清單 6 sample.xml
|
當(dāng)我們得到 XML 示例文檔的時候,就可以對照其結(jié)構(gòu)進(jìn)行 XML 查詢或視圖的開發(fā)了,只需要將 XML 文檔中元素與元素的嵌套關(guān)系轉(zhuǎn)化為 XMLELEMENT、XMLATTRIBUTES、XMLNAMESPACES 等 XML 函數(shù)的嵌套關(guān)系。一般的手工修改方法是:將起始標(biāo)簽<element>替換為"XMLELEMENT(NAME "element",";當(dāng)該元素具有屬性或者命名空間聲明,需要緊接著加入相應(yīng)的 XMLATTRIBUTES 或 XMLNAMESPACES 語句;如果這是一個含有文本內(nèi)容的葉子節(jié)點,則要將文本內(nèi)容修改為 SQL 常量(如:'CONSTANT')或者 SQL 字段(如:tbl.colname);最后把結(jié)束標(biāo)簽替換為")",并列的一組元素修改完畢后,應(yīng)用逗號分隔。為了避免不必要的疏忽,應(yīng)該遵循嵌套的元素從外到內(nèi),并列的元素從前往后的順序在進(jìn)行處理。
![]() ![]() |
![]()
|
編寫 XML 查詢的過程如果完全用手工來實施,需要開發(fā)者有清晰的思路和良好的編輯習(xí)慣,從技術(shù)難度上講沒有太多問題,但處理較為復(fù)雜的 XML 文檔結(jié)構(gòu)時,開發(fā)人員需要非常仔細(xì)地將 XML 文檔中每個元素節(jié)點與數(shù)據(jù)庫中的字段進(jìn)行對應(yīng),并且根據(jù)樣例組織成復(fù)雜的 XML 結(jié)構(gòu),工作量比較大,變得相當(dāng)麻煩并且容易出錯。
作者根據(jù)實際開發(fā)的 XML 查詢的經(jīng)驗,編寫了一個小程序,用于將樣例 XML 文檔轉(zhuǎn)化成 XML 查詢框架,即一個可以產(chǎn)生目標(biāo)結(jié)構(gòu)的 XML 文檔 SQL 查詢,其中所有的元素、屬性值等都直接使用來自樣例 XML 中的內(nèi)容轉(zhuǎn)化為常量。生成的 XML/SQL 查詢語句,可以直接在 DB2 中執(zhí)行,在很大程度上減輕了開發(fā)人員的工作量,提高了工作效率。
此程序的代碼附于本文后,可供讀者下載使用或參考。該程序使用 Java 語言完成,只有一個包含 Main 函數(shù)的類:xmlutol.Xml2DB2view,在處理 XML 文件的過程中使用了開源的 dom4j 項目。這個類接受兩個參數(shù),前一參數(shù)是輸入 XML 文檔的文件名,后一參數(shù)是輸出 SQL 腳本的目標(biāo)文件名。
我們將清單6中的sample.xml傳給該程序處理,可以得到初步的 SQL 框架。
清單 7 調(diào)用 xmlutol.Xml2DB2view
|
檢查 views.sql 中生成的 SQL 內(nèi)容:
需要被替換的數(shù)據(jù)常量用紅色粗體標(biāo)出
清單 8 生成的 views.sql
|
在接下來的過程中,需要將查詢中的引用的 sysibm.sysdummy1 表、常數(shù)內(nèi)容等替換成目標(biāo)表和相應(yīng)的數(shù)據(jù)列,如果需要還應(yīng)該加入聚集、Null 值處理等邏輯, 以及使用 XMLFOREST 函數(shù)對查詢進(jìn)行精簡。由于這些修改非常靈活,而且對于每個任務(wù)可能會很特殊,所以不便用簡單的程序來實現(xiàn),所幸這部分修改的工作量相對較小。
![]() ![]() |
![]()
|
以清單 8 中的查詢腳本為基礎(chǔ),通過適當(dāng)?shù)男薷模涂梢酝瓿砂l(fā)布 Customer 與 Contact 數(shù)據(jù)的 XML 查詢。
在得到 XML 查詢框架之后,就應(yīng)寫出讀取目標(biāo)數(shù)據(jù)的常規(guī) SQL,如果覺得有必要還可以根據(jù)此查詢整理出從查詢數(shù)據(jù)列到 XML 文檔元素的映射關(guān)系列表,方便后續(xù)的修改。
清單 10 SQL 常規(guī)查詢,及其 XML 映射關(guān)系
|

根據(jù)上面的列表,我們逐一將 XML 查詢框架中的常量用 SQL 查詢的字段替換,同時也用 SQL 查詢的 From 語句塊替換掉 XML 查詢框架的"FROM sysibm.sysdummy1"部分。
聚集處理:
將這個查詢應(yīng)用入 XML 查詢時,由于 customer 與 contact 是一對多的關(guān)系,根據(jù)設(shè)計 XML 查詢中的單條記錄對應(yīng)一條 customer 記錄,所以我們需要在 XML 查詢中對來自 contact 表的部分進(jìn)行聚集,即對 <cnt:Contact> 元素進(jìn)行聚集。
清單 11 <cnt:Contact> 聚集片斷
|
NULL 值處理:
通常情況下,XML文檔中某些可選元素的源數(shù)據(jù)在數(shù)據(jù)庫中可能為空值,而XMLELEMENT函數(shù)接收NULL值,會在XML文檔中產(chǎn)生形如<Element></Element>的空節(jié)點。對于XML文檔的處理時,我們一般不希望顯示這樣的空節(jié)點。對于這樣的情況,可以通過清單12的方式進(jìn)行處理。
清單12 NULL 值處理
|
當(dāng) cnt.address2 為空值時,上述的語句中的"cnt:AddressLine2"節(jié)點將不會出現(xiàn)在生成的 XML 中,XML 結(jié)構(gòu)將是:
|
如果有很多可選節(jié)點,也可以通過程序來生成框架,只需要給樣例 XML 文檔的相應(yīng)節(jié)點添加 optional 屬性并賦為"true",譬如 <BusinessArea optional="true">AP</BusinessArea>,通過我們的程序即可完成對其的處理。
經(jīng)過上述修改就完成了最終的 XML 查詢語句,在清單 13 中,已把在生成的 XML 查詢框架基礎(chǔ)上的修改用藍(lán)色粗體標(biāo)注出來,其中 BusinessArea,cnt:JobTitle,cnt:Cellphone,cnt:Location ,cnt:Fax 和 cnt:AddressLine2 元素為可選節(jié)點。
清單13 最終 XML 查詢
|
根據(jù)這個查詢得到 XML 文檔,參見下載中的 result.xml。
![]() ![]() |
![]()
|
本文主要介紹了 DB2 提供的基本的 XML 函數(shù),并且給出了具體的開發(fā)實例,讀者可以通過本文了解如何根據(jù) XSD 文檔或者 XML 樣例進(jìn)行試圖和查詢的開發(fā)。另外,DB2 Extender 提供了更為方便的創(chuàng)建 XML 視圖或查詢的功能,但是一般情況下需要對現(xiàn)有數(shù)據(jù)庫進(jìn)行升級和配置。而在一個產(chǎn)品的生命周期中,會存在多個數(shù)據(jù)庫服務(wù)器作為開發(fā)、測試、維護(hù)和產(chǎn)品運行所使用。為這些數(shù)據(jù)庫增加 Extender 功能會增加 DBA 的工作量,還會增加產(chǎn)品環(huán)境停止服務(wù)的時間。但是通過本文的介紹,并結(jié)合筆者開發(fā)的工具使用,只利用 DB2 提供的基本 XML 函數(shù),同樣可以很方便快捷的開發(fā) XML 視圖和查詢。
![]() ![]() |
![]()
|
名字 | 大小 | 下載方法 |
---|---|---|
0609zhangdw.zip | 298K | HTTP |
![]() |
||||
![]() |
關(guān)于下載方法的信息 |
![]() |
![]() |
Get Adobe? Reader? |
![]() ![]() |
![]()
|
![]() ![]() |
![]()
|
![]() |
||
|
![]() |
陳力,北京師范大學(xué)信息管理專業(yè)研究生,在IBM CSDL Beijing的DSW ODS組實習(xí)。熟悉DB2,J2EE等技術(shù),對Web應(yīng)用、Web Services以及Java技術(shù)很感興趣。 |
![]() |
||
|
![]() |
張大為,IBM CSDL 軟件工程師. 目前從事DB2相關(guān)工作,主要對電子商務(wù)應(yīng)用進(jìn)行數(shù)據(jù)支持。對DB2、Unix、Web Services以及Java技術(shù)很感興趣。 |