學(xué)習如何用SQL Server的XML特征為你的數據庫提供新的功能。
如果你在IT業(yè)工作,那么你很可能聽(tīng)說(shuō)過(guò)XML;但如果你的工作主要與SQL Server有關(guān),那么你可能并沒(méi)有直接運用過(guò)XML。XML已經(jīng)是Web編程環(huán)境中的普遍的數據格式了,而且它也是.NET Framework中主要的底層技術(shù)之一。SQL Server以?xún)煞N方式來(lái)支持XML:通過(guò)SQL Server本身的功能,以及通過(guò)發(fā)布稱(chēng)為SQLXML的額外的功能。SQLXML擴展了SQL Server,并提供了XML兼容性。在本月的專(zhuān)欄中,我將講述SQL Server對XML的內置的支持,并講述通過(guò)發(fā)布SQLXML而增加的一些功能(見(jiàn) 圖1)。SQL Server支持XML就意味著(zhù),我們可以更有效地更新和讀取數據了;我們不再需要將XML數據轉換成數據庫可以理解的另一種格式,或將XML數據從數據庫轉換成XML。而且,可供開(kāi)發(fā)人員選擇的方法也更多了,就是說(shuō),他們在訪(fǎng)問(wèn)數據方面更靈活了。
對XML的宣傳已經(jīng)有很多了,所以重要的一點(diǎn)是要意識到它只是一門(mén)簡(jiǎn)單的技術(shù)。本質(zhì)上,它是用來(lái)描述數據的一個(gè)標準的文件格式。(有關(guān)XML基礎知識的更多的信息,請參閱工具條“XML 101”。)從發(fā)布SQL Server 2000的最初版本以來(lái),對XML的支持就已經(jīng)是SQL Server的一部分了。SQL Server不是通過(guò)提供一個(gè)方法保存XML文件來(lái)支持XML的,而是提供了一個(gè)到關(guān)系數據的接口,使你可以在表和其它數據庫對象中讀寫(xiě)XML數據。SQL Server所固有的XML功能包括:可以通過(guò)HTTP、模板查詢(xún)、FOR XML子句和OPENXML()函數來(lái)訪(fǎng)問(wèn)SQL Server。接下來(lái),我將講述這些功能是如何運作的,以及它們可以如何使你的企業(yè)受益。
圖1. 提供 XML支持
要通過(guò)HTTP訪(fǎng)問(wèn)一個(gè)SQL Server數據庫,你必須首先設置一個(gè)虛擬目錄。這個(gè)虛擬目錄在HTTP協(xié)議和一個(gè)特定的數據庫之間提供了一個(gè)鏈接。設置虛擬目錄時(shí),我們需要用“Configure SQL XML Support In IIS”菜單條目,你可以在Window的Start菜單中的SQL Server菜單條目找到該項。通過(guò)該菜單條目,你就可以指定虛擬目錄的名稱(chēng)、物理路徑、服務(wù)器名稱(chēng)、數據庫名稱(chēng)和注冊信息。一旦你創(chuàng )建了一個(gè)虛擬目錄,你就可以通過(guò)一個(gè)URL將查詢(xún)發(fā)送到數據庫了。如果你設置了一個(gè)叫做Northwind的虛擬目錄,并在瀏覽器中輸入了查詢(xún)
http://localhost/Northwind?sql=SELECT+*+FROM+Shippers+FOR+XML+AUTO,ELEMENTS+&root=Shippers,它就會(huì )返回類(lèi)似于“XML 101”工具條中的Shippers例子中的XML數據。與運用ADO或其它任何技術(shù)相比,HTTP查詢(xún)會(huì )讓我們更容易地來(lái)訪(fǎng)問(wèn)網(wǎng)站或Web應用程序的數據。 對于一個(gè)簡(jiǎn)單的查詢(xún)語(yǔ)句來(lái)說(shuō),HTTP查詢(xún)會(huì )很好,但對于一個(gè)更復雜的查詢(xún)來(lái)說(shuō),這種格式就會(huì )變得難以理解并很難管理了。這種方法也不安全,因為查詢(xún)源代碼是暴露給用戶(hù)的。另外一種可選方法是在HTTP上調用一個(gè)模板查詢(xún)。一個(gè)模板查詢(xún)就是一個(gè)包含SQL查詢(xún)的XML文件。模板作為文件保存在服務(wù)器上。因此,如果你在一個(gè)叫做GetShippers.xml的模板中封裝了Shippers SELECT查詢(xún),那么URL查詢(xún)的形式就會(huì )是:
http://localhost/Northwind/templates/GetShippers.xml。模板也可以帶有參數,當你的模板調用一個(gè)存儲過(guò)程時(shí),該功能會(huì )很有用。在URL查詢(xún)和模板查詢(xún)中,如果你想從查詢(xún)返回一個(gè)HTML頁(yè)面,那么你可以指定一個(gè)XSLT樣式表,將它用于XML。模板查詢(xún)是讀取數據的一個(gè)更安全的方法,它可以被緩存以得到更好的性能。
你也可以用FOR XML子句將數據讀取成XML格式,該方法從SQL Server表中返回數據,你可以把它們看做是XML數據。你可以在一個(gè)SELECT語(yǔ)句中運用FOR XML子句,它有三種模式可以以不同的格式來(lái)返回XML:RAW、AUTO和EXPLICIT。RAW模式將結果中的每個(gè)記錄作為一個(gè)普通的行元素來(lái)返回,它被包含在一個(gè)<row/>標簽中,并將每個(gè)列的值作為一個(gè)屬性。AUTO模式將每個(gè)記錄作為行元素返回,根據源表或視圖對它進(jìn)行命名。如果查詢(xún)從一個(gè)表返回多個(gè)列,那么每個(gè)列的值就會(huì )被作為表元素的屬性來(lái)返回。但最重要的是,如果你的SELECT語(yǔ)句執行了合并操作,那么AUTO模式就代表的是子行,它們作為元素嵌套在父行下。EXPLICIT模式有幾個(gè)參數,你可以通過(guò)這些參數完全定義返回的XML的樣式。你可以為每個(gè)元素定義標簽,明確確定數據是如何嵌套的。FOR XML語(yǔ)句使我們不必再返回一個(gè)rowset,然后在客戶(hù)端或中間層將它轉換成XML了。
OPENXML函數可以讓你像操作一個(gè)表那樣來(lái)運用XML數據,可以將它們轉換成內存中的一個(gè)rowset。要運用OPENXML,首先要調用sp_xml_preparedocument存儲過(guò)程,實(shí)際上,它將XML解析成一個(gè)數據樹(shù),并將那個(gè)數據的句柄傳遞到OPENXML函數。然后你就可以操作那個(gè)數據了:進(jìn)行查詢(xún)、將它插入到表中、等等。OPENXML函數可以帶有三個(gè)參數:用于XML文檔內部顯示的句柄、一個(gè)rowpattern參數和一個(gè)flags參數。Rowpattern參數指定了應該返回原始的XML文檔中的哪些節點(diǎn)。Flags參數指定了以屬性為中心的映射(結果集中列名符合屬性名)或以元素為中心的映射(結果集中列名符合元素名)。在處理完XML數據后,我們可以調用sp_xml_removedocument將XML數據從內存中刪除。
通過(guò)SQLXML得到更多的支持
通過(guò)發(fā)布SQLXML(也被稱(chēng)為Web版),Microsoft也在SQL Server中提供了更多的XML支持。已經(jīng)有三個(gè)SQLXML的版本了,它們包含的一些額外的功能有updategram和XML Bulk Load。你可以在線(xiàn)下載最新的版本SQLXML 3.0(見(jiàn)資源)。你可以通過(guò)基于XML的模板,運用updategram來(lái)插入、更新或刪除表中的數據。該模板有一個(gè)before block,它描述了記錄更新前的當前狀態(tài);還有一個(gè)after block,它描述了記錄的變化。下面就是updategram的一個(gè)例子,它修改了Shippers表中的一個(gè)公司的Phone字段:
<updg:sync >
<updg:before>
<Shippers ShipperID="3" />
</updg:before>
<updg:after>
<Shippers Phone="(503) 555-0108" />
</updg:after>
</updg:sync>
在缺省情況下,updategrams認為before block和after block中的字段指的是表和列。但updategrams也可以用一個(gè)mapping schema。Mapping schema將一個(gè)XML文檔中的元素與一個(gè)表中的元素關(guān)聯(lián)了起來(lái)。如果在上面的模板中,你引用屬性名SID,而不是ShipperID,那么mapping schema就會(huì )將SID映射到ShipperID列。你可以通過(guò)HTTP(同模板查詢(xún)一樣)或通過(guò)ADO將updategrams發(fā)送到SQL Server。它們也可以被參數化,帶有輸入值。Updategrams提供了一個(gè)方法,使我們可以直接從XML更新SQL Server數據,這樣就不用從XML文檔得到數據,然后再用一個(gè)記錄集或調用一個(gè)存儲過(guò)程了。Updategrams只是可以簡(jiǎn)單地插入、更新或刪除數據,所以如果你需要查看一個(gè)值是否存在、或在更新前查看一些商業(yè)規則,那么你就應該用OPENXML。
雖然你可以用OPENXML函數和updategrams來(lái)插入數據,但對于加載大量的XML數據來(lái)說(shuō),這兩種方法都不實(shí)用。你應該用XML Bulk Load將大量的XML數據插入到SQL Server表中。實(shí)際上,我們是用SQLXMLBulkLoad組件來(lái)加載數據的,你可以從一個(gè)客戶(hù)端應用程序來(lái)調用這個(gè)組件。在建立到數據庫的連接后,bulk load組件需要一個(gè)路徑來(lái)訪(fǎng)問(wèn)mapping schema,從而將XML屬性和元素映射到數據庫對象,而且還需要路徑來(lái)訪(fǎng)問(wèn)一個(gè)XML文檔或一個(gè)XML流。在Bulk Load組件中,你可以指定是否執行數據表檢查約束(check constraint)、是否忽略通過(guò)復制鍵添加的記錄、當插入數據時(shí),是否應該鎖定數據表,等等。
缺省情況下,大量加載不是事務(wù)處理型(transactional)的,所以如果出現錯誤,截止到錯誤點(diǎn)前插入的數據就會(huì )保留在數據庫中。你可以指定所有加載的數據都是在一個(gè)單獨的事務(wù)處理過(guò)程中的,因此該過(guò)程要么會(huì )十分成功,要么會(huì )回滾。如果你用了事務(wù)處理,所有的數據在插入前都會(huì )被寫(xiě)進(jìn)一個(gè)臨時(shí)的文件。這就意味著(zhù),你需要足夠的磁盤(pán)空間來(lái)保存臨時(shí)文件,而且加載數據可能會(huì )相當慢。XML Bulk Load給我們提供了一個(gè)很好的方法,使我們可以將大量的數據寫(xiě)到SQL Server中;否則,你就必須提取數據,然后用另外的方法將它加載到你的數據庫中。
你也可以配置SQL Server來(lái)緩存XSLT樣式表、模板和mapping schema,從而得到更好的性能。根據具體實(shí)現情況,你可以在Web應用程序中用通過(guò)HTTP和XSLT的XML查詢(xún)來(lái)替代標準的ASP/ADO數據訪(fǎng)問(wèn),從而得到HTML輸出結果,這種方法可以極大地提高性能。
以上就是SQL Server對XML的一些高級支持。不管我們對它的宣傳有多少,XML的功能就這么多了。因為XML是用來(lái)顯示數據的一個(gè)標準,也是用于.NET的數據傳輸技術(shù),因此,XML與SQL Server的集成能力就會(huì )是企業(yè)需要解決的一個(gè)重要的問(wèn)題。