| 以文本方式查看主題 - DCMS先鋒論壇 (http://www.soft.e531.com/index.asp) -- Sql Server技術(shù)交流 (http://www.soft.e531.com/list.asp?boardid=6) ---- SQL Server 2005中的XML的最佳實(shí)踐 (http://www.soft.e531.com/dispbbs.asp?boardid=6&id=57) |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:25:57 -- SQL Server 2005中的XML的最佳實(shí)踐 Microsoft SQL Server 2005 對XML數據處理提供了廣泛的支持。XML值可以以原生的形式存儲在具有XML數據類(lèi)型的列中,它們可以是有類(lèi)型的XML(typed XML),或者是無(wú)類(lèi)型的XML(untyped XML)。你可以對XML列添加索引。此外,還可以使用XQuery和XML DML來(lái)精細地操作數據,后者已成為數據修改功能的擴展。 Microsoft SQL Server 2000和SQLXML web版提供了強大的XML數據管理能力。他們主要體現在關(guān)系型數據和XML數據的映射上。關(guān)系型數據的XML視圖可以用帶注解的XSD(AXSD)定義,來(lái)提供一個(gè)以XML為中心的方法用以支持數據的大量裝載,查詢(xún),以及對xml數據的改寫(xiě)能力。T-SQL擴展提供了一個(gè)以SQL為中心的方法來(lái)實(shí)現關(guān)系型的查詢(xún)結果映射成XML(使用FOR XML子句),以及從XML來(lái)生成關(guān)系型視圖(用OpenXML)。這些支持將在SQL Server 2005中得到更多的擴展。加上最新增加的原生XML支持功能,SQL Server 2005提供了一個(gè)強大的平臺用來(lái)開(kāi)發(fā)和管理半結構化和非結構化數據應用。 本文檔提供了一些SQL Server 2005中XML數據建模和使用的指導。它分為以下兩個(gè)主題: ·數據建模 XML數據可以以多種形式儲存在SQL Server 2005中,例如,可以將原生XML數據類(lèi)型或者是一個(gè)XML文檔數據的一部分存儲在表中。這個(gè)主題將指導大家如何正確的數據建模,還將涉及到如何對XML數據進(jìn)行索引,屬性提升(property promotion,),XML實(shí)例的類(lèi)型化。 ·用法 這個(gè)主題將討論XML數據使用方面的內容,諸如裝載XML數據到server中,輸入推論在查詢(xún)編輯中(and type inference in query compilation);解釋和區分相近的特性;對這些特性的建議用法。還用例子來(lái)做個(gè)演示。 如果想更好的閱讀本文檔,建議先對SQL Server中的XML特性有個(gè)基本的了解??梢圆榭?a target="_blank">XML Support in Microsoft SQL Server 2005. 數據建模 這一部分簡(jiǎn)要的介紹了在SQL Server 2005中使用XML的原因,并對如何選擇原生XML存儲或XML視圖技術(shù)提供了一些指導,和數據建模方面的建議。 關(guān)系型還是XML數據模型 如果數據具有高度的結構化和熟悉的架構,那么采用關(guān)系型模型存儲數據更合適。微軟SQL Server為此提供了必要的功能和相應的工具。另一方面,如果數據結構很靈活(半結構化或無(wú)結構化)或者結構未知,那你就必須為這些數據考慮合適的數據模型。 XML是個(gè)好的選擇,如果你還希望這個(gè)數據模型是平臺獨立的,數據能夠在結構化和語(yǔ)義標記間保持靈活的話(huà)。此外,如果考慮到下面幾個(gè)因素的話(huà),就更合適了: ·數據稀疏,或者數據結構未知,或者是數據結構將來(lái)會(huì )有較大的改變。 ·數據需要表現出層次性(并非實(shí)體之間的引用)且可能有遞歸。 ·數據內含順序特性。 ·你希望根據數據的結構來(lái)查詢(xún)或更改部分數據。 如果你不需要滿(mǎn)足上面這些條件,那么你應該選擇關(guān)系型數據模型。例如,如果你的數據是XML格式的,但應用程序僅僅是存儲和檢索它,那么一個(gè)[n]varchar(max)列足夠了。將數據存儲在XML列有額外的優(yōu)點(diǎn):存儲引擎會(huì )檢查數據是否具有良好的格式、合法性,且支持對XML數據的精細的查詢(xún)和修改。 在SQL Server 2005存儲XML數據的原因 下面是選擇在SQL Server 2005中存儲XML數據而非在文件系統中管理XML數據的原因: ·你希望能利用數據庫服務(wù)器的管理特性來(lái)管理XML數據(如,備份、恢復、復制)。 ·你希望能夠以有效的、交易化的方式來(lái)共享、查詢(xún)和修改XML數據。對你的應用程序而言,精細的數據訪(fǎng)問(wèn)很重要。例如,你可能希望提取XML文檔中的某一部分,或者是希望插入一個(gè)新的部分而不是替換整個(gè)文檔。 ·你已有關(guān)系型的數據和應用程序,并且你希望在你的應用程序中關(guān)系型數據和XML數據間能互操作,你需要一個(gè)能夠在整個(gè)應用程序中查詢(xún)和修改數據的語(yǔ)言。 ·你希望服務(wù)器能夠保證數據的良好結構性,且能根據XML架構驗證數據。 ·你希望能夠對XML數據添加索引來(lái)獲得更有效的查詢(xún)處理和更好的擴展性。 ·你希望能夠用SOAP、ADO.NET、OLE DB來(lái)訪(fǎng)問(wèn)XML數據。 如果不存在上面這些情況,把數據存儲為非XML的,大對象類(lèi)型的如[n]varchar(max) 或 varbinary(max)更為合適。不然,你還是應該采用XML來(lái)存儲數據。 XML存儲選項 SQL Server 2005中XML數據存儲選項如下: ·作為XML數據類(lèi)型來(lái)存儲: 這種存儲方式將保留XML數據的內容,如層次性、文檔順序、元素和屬性值等。特別是XML數據的InfoSet內容被保留(更多InfoSet信息,請參見(jiàn)http://www.w3.org/TR/xml-infoset)。它不是XML文本的原樣拷貝,它忽略了一些信息:無(wú)意義的空格、屬性的順序、命名空間前綴、XML聲明。 對有類(lèi)型的XML數據類(lèi)型(也就是說(shuō)XML數據類(lèi)型和XML架構相關(guān)聯(lián)),post-schema validation Infoset (PSVI,它將類(lèi)型信息加入Infoset)被編碼到XML數據的內部表示中,這將顯著(zhù)提高語(yǔ)法分析速度。(更多信息,請查閱W ·把XML數據映射成關(guān)系型數據來(lái)存儲: 通過(guò)AXSD,XML數據被分解到一個(gè)或多個(gè)表的列中,在關(guān)系級別上忠實(shí)的保留了數據——層次結構被保留,然而元素的順序被忽略了。架構不可被回歸,操作不可逆。 ·大對象存儲([n]varchar(max) 和 varbinary(max)): 這種方式是XML數據的原樣拷貝。這種方法對于一些特定的應用很有用,如法律文本的保存。大多數應用并不需要原樣拷貝,忠實(shí)的Infoset XML內容就足夠了。 一般來(lái)說(shuō),可能需要把這幾種方式結合起來(lái)使用。例如,你可能需要把XML數據存儲在XML數據類(lèi)型列中,并且要把其屬性提升到關(guān)系型的列中。反過(guò)來(lái)說(shuō),你也可能希望使用映射技術(shù)來(lái)將非遞歸的部分存儲在非XML的列中,在XML數據類(lèi)型列中只存儲遞歸部分。 XML技術(shù)的選擇 在選擇原生XML還是XML視圖時(shí),一般需要考慮下面幾個(gè)因素: ·存儲選項: 你的XML數據可能適合采用大對象存儲(如,產(chǎn)品手冊),也可能適合存儲在關(guān)系型的數據列中(如行項目轉化為XML數據)。每種存儲選項對文檔忠實(shí)度的保留程度也不一樣。 ·查詢(xún)能力: 由于你的查詢(xún)XML數據的需要,你可能會(huì )覺(jué)得某種存儲方式比另外的更適合。例如,對XML節點(diǎn)的謂詞評估,在不同的存儲選項中對此支持的程度也不同。 ·XML數據索引: 你可能希望索引XML數據以提高XML查詢(xún)性能。不同的存儲選項有著(zhù)不同的索引方法,你需要選擇一個(gè)合適的方法來(lái)優(yōu)化應用。 ·數據修改能力: 某些應用需要對XML數據能夠精細的修改(如,在一個(gè)XML文檔中增加一個(gè)新的部分), 有的則不需要(如web內容管理)。語(yǔ)言對數據修改能力的支持可能對你的應用程序很重要。 ·架構支持: 你的XML數據可能需要用架構來(lái)描述,它可能是一個(gè)XML架構文檔,也可能不是。不同的XML技術(shù)對架構綁定的XML支持也不同。 很明顯,不同的選擇會(huì )導致系統有不同的性能表現。 原生XML存儲 你可以存儲XML數據在數據庫服務(wù)器的XML數據類(lèi)型列中,這種存儲方式適用于: ·你希望有種直截了當的方法把XML數據存儲在服務(wù)器中,同時(shí)保留XML文檔的順序和結構。 ·你的XML數據可能有架構與其相關(guān)聯(lián)。 ·你希望能夠查詢(xún)和修改XML數據。 ·你希望能夠對XML數據加索引以提高查詢(xún)速度。 ·你的應用程序需要系統編目視圖來(lái)管理XML數據和XML架構。 如果你的XML文檔結構很大,或者XML文檔需要和不同的XML架構、復雜的XML架構 例:用XML數據類(lèi)型對XML數據建模 想象一下這個(gè)場(chǎng)景:產(chǎn)品手冊采用XML格式,每個(gè)主題有各自的章節,每章中有多個(gè)段落(section)。段落還包含子段落,因此<section>是個(gè)遞歸的元素(element)。產(chǎn)品手冊還包含大量的混合內容、圖表、技術(shù)資料等,數據是半結構化的。用戶(hù)希望能夠對感興趣的主題執行語(yǔ)義查找(如”indexing”章節中的”clustered index”段落),這里,對XML文檔的合適的存儲模型是XML數據類(lèi)型列。這將保留XML數據的Infoset內容,并且可以對XML加索引提高查詢(xún)速度。 例:保持XML數據的原樣拷貝 假如政府規章(XML文檔格式)要求完全的原樣拷貝(如,簽署的文檔、法律文檔、股票交易單等),你可能需要存儲該文檔在[n]varchar(max)列中。 對查詢(xún)而言,SQL Server將在運行是轉化數據為XML數據,并且對其執行Xquery操作。運行時(shí)的轉化可能非常消耗資源,特別是當文檔很大時(shí)。如果你需要頻繁的查詢(xún),你應該額外存儲文檔在一個(gè)XML數據列中,并對其加索引,僅在需要原樣文檔時(shí)才從[n]varchar(max)列中取得。 XML列可以是基于[n]varchar(max)列的計算列。你不能在XML計算列上創(chuàng )建XML索引,然而,你也不能在[n]varchar(max) 或 varbinary(max) 列上創(chuàng )建XML索引。 XML視圖技術(shù) 借助于在XML架構和數據庫的表之間定義映射,你可以為永久數據(不被改寫(xiě)的)創(chuàng )建“XML視圖”。XML大容量裝載功能可以被用來(lái)往使用XML視圖的基礎表上裝填數據。你可以使用XPath 1.0 查詢(xún)XML視圖,該查詢(xún)被翻譯成施加在表上的SQL查詢(xún)。同樣的,改寫(xiě)也是這么做的。 這項技術(shù)適用于下面幾種場(chǎng)合: ·你希望你的編程模型以XML為中心,這樣你可以使用XML視圖在已存在的關(guān)系型表上。 ·你的XML數據有架構對應(XSD, XDR),該架構是你的外部合作伙伴所提供的。 ·XML數據的順序不重要,或者是需查詢(xún)的數據不是遞歸的,或者是將來(lái)的最大遞歸深度已知。 ·你希望使用XPath 1.0 來(lái)通過(guò)XML視圖查詢(xún)和修改數據。 ·你希望能大容量裝載XML數據并且能把它分解到使用XML視圖的基表中。 關(guān)系型的數據被暴露為XML數據用于數據交換和web service,帶固定架構的XML數據。更多信息,請參見(jiàn)the SQLXML Developer Center. 例:使用帶注解的XML架構(AXSD)對數據建模 假設你已有關(guān)系型數據(諸如客戶(hù)信息,訂單信息),你希望把它作為XML數據來(lái)操作。你可以在關(guān)系型數據上使用AXSD來(lái)定義一個(gè)XML視圖。這個(gè)XML視圖允許你大量導入XML數據到表中,并且能夠借助它查詢(xún)和修改關(guān)系型數據。如果你需要和其他應用程序交換XML數據,同時(shí)不影響SQL應用程序的正常運行,采用這種建模非常有用。 混合模型 常見(jiàn)的數據建模情況是結合了關(guān)系型和XML數據類(lèi)型的混合模型。XML數據中的一些值可以存儲在關(guān)系型的數據列中,剩余的、也可以是全部的XML值被存儲在XML列中。這會(huì )導致較好的性能(如,你可以完全控制關(guān)系型列上的索引)和鎖的特性。然而,你必須對管理數據的存儲付出更多的勞動(dòng)。 怎樣把值存儲在關(guān)系型列中依賴(lài)于你的實(shí)際情況。例如,如果你基于路徑表達式/Customer/@CustId檢索整個(gè)XML值,接著(zhù)提升(promoting)CustId屬性值到關(guān)系型列中,對該列加索引,將會(huì )得到很快的查詢(xún)速度。另一方面, 如果你的XML數據被徹底的且不帶冗余的分解到關(guān)系型的列中,重新拼裝的代價(jià)可能會(huì )很高。 對于那些有著(zhù)高度結構化的XML數據(如,表的內容可以被轉換成XML數據),你可以使用XML視圖技術(shù)映射所有的值到關(guān)系型的列中。 使用XML數據類(lèi)型的數據建模這一部分將討論原生XML存儲方式下的數據建模。包括:索引XML數據、屬性提升(property promotion)、有類(lèi)型(typed)的XML數據類(lèi)型。 同一個(gè)表中或不同表 XML數據類(lèi)型列可以關(guān)系型列在一個(gè)表中共存,也可以單獨在另一張表中,通過(guò)主外鍵的方式和主表相聯(lián)。 當滿(mǎn)足下面條件時(shí),可以創(chuàng )建XML數據類(lèi)型列和關(guān)系型列在同一張表中: ·應用程序從XML數據列上檢索數據,但并不要求其上有XML索引 或者 ·你希望在XML數據類(lèi)型列上構建索引,主表的主鍵就是表的聚集索引。 當滿(mǎn)足下面條件時(shí),在另一張表中創(chuàng )建XML數據類(lèi)型列: ·你希望在XML數據類(lèi)型列上構建XML索引,但主表的主鍵不是聚集索引,或者主表沒(méi)有主鍵,或者主表沒(méi)有聚集索引。 ·你不希望由于表中XML列的原因導致表掃描速度下降,不管它是in-row存儲還是out-of-row存儲。 XML數據粒度 存儲在XML列中的XML數據粒度對鎖和改寫(xiě)特性至關(guān)重要。SQL Server 采用同樣的鎖機制對XML數據和非XML數據,因此,行級鎖將造成一行中的所有XML實(shí)例被鎖。當粒度較大時(shí),更大的XML實(shí)例被鎖將導致在多用戶(hù)環(huán)境下的吞吐量下降。另一方面,過(guò)度的分解(粒度較?。е聦ο蠓庋b的丟失和重新拼裝代價(jià)的提高。 在數據建模需求和鎖、改寫(xiě)特性之間的平衡,對一個(gè)好的設計是非常重要的。 無(wú)類(lèi)型、有類(lèi)型和受約束的XML數據類(lèi)型 SQL Server 2005 XML數據類(lèi)型實(shí)現了ISO SQL-2003所定義的 標準XML數據類(lèi)型。同樣,它可以存儲良好結構的XML 1.0 文檔,以及所謂的帶文本節點(diǎn)和任意數量的頂級元素的XML內容片段在無(wú)類(lèi)型的XML列中。系統會(huì )檢查數據是否是良好結構的,并不要求該列被綁定到XML架構上,同時(shí)在引伸意義(extended sense)拒絕不具備良好結構的數據。這對無(wú)類(lèi)型的XML變量和參數也一樣。 如果你有XML架構來(lái)描述XML數據,你將能夠把架構和XML列關(guān)聯(lián)起來(lái)產(chǎn)生有類(lèi)型(typed)XML。相對于無(wú)類(lèi)型的XML而言,在查詢(xún)和數據修改語(yǔ)句的編譯時(shí),XML架構被用來(lái)校驗數據,執行更精確的類(lèi)型檢查,此外,它還能優(yōu)化查詢(xún)和存儲處理。 在下面情況下使用無(wú)類(lèi)型的XML數據類(lèi)型: ·你的XML數據沒(méi)有架構 ·你有XML架構,但你不希望服務(wù)器校驗數據。有時(shí)有這種情況:應用程序在存儲數據到服務(wù)器之前在客戶(hù)端校驗數據,或者是臨時(shí)地根據架構存儲非法的XML數據,或者是服務(wù)器不支持這種架構成分(如key/keyref)。 在下面情況下使用有類(lèi)型的XML數據類(lèi)型: ·你的XML數據有XML架構,同時(shí)你還希望服務(wù)器能根據XML架構校驗XML數據。 ·你希望能夠根據類(lèi)型信息在存儲和查詢(xún)方面的得到好處 ·你希望在編譯查詢(xún)時(shí)得到 有類(lèi)型的XML列,參數和變量都能夠存儲XML文檔或者內容,只要你在聲明時(shí)分別的指定標記(DOCUMENT 或 CONTENT),此外,你還可以提供XML架構集。如果每個(gè)XML實(shí)例都有完整的一個(gè)頂級元素,那么指定DOCUMENT,否則指定CONTENT。查詢(xún)編譯器在編譯時(shí)使用DOCUMENT標記進(jìn)行類(lèi)型檢查,推斷出單獨的頂級元素。 除了類(lèi)型化一個(gè)XML列之外,你還可以使用關(guān)系型的約束(列約束或者是行約束)在有類(lèi)型或者是無(wú)類(lèi)型的XML數據類(lèi)型列上,通常使用在下面的場(chǎng)合: ·你的商業(yè)規則不能被表示為XML架構。例如下面這個(gè)商業(yè)規則,花店的送貨地址必須在花店的 ·你的約束包含表中的其他XML列或非XML列,一個(gè)例子是客戶(hù)ID的強制性(/Customer/@CustId),它被建立在一個(gè)XML實(shí)例上,用來(lái)匹配關(guān)系型CustomerID列的值。 文檔類(lèi)型定義(DTD) XML數據類(lèi)型列,變量和參數可以用XML架構來(lái)類(lèi)型化,但不能用DTD來(lái)做。然而,行內(inline)的DTD可以被用來(lái)對有類(lèi)型和無(wú)類(lèi)型的XML提供默認值,和替換實(shí)體引用。 你可以使用第三方工具轉換DTDs為XML架構文檔,再把它加載到數據庫中。 |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:32:39 -- 索引XML數據類(lèi)型列 可以在XML數據類(lèi)型列上創(chuàng )建XML索引。它將索引列中XML實(shí)例的所有標簽(tags)、值和路徑,并且提高了查詢(xún)性能。在下面的場(chǎng)合中,應用程序將從XML索引中受益: ·你的工作常要查詢(xún)XML列。在數據被修改時(shí)的XML索引維護成本必須要考慮進(jìn)去。 ·XML值比較大同時(shí)要檢索的部分比較小,建立索引將避免解析整個(gè)數據,從而提高查詢(xún)效率。 在XML列上所建的第一個(gè)索引被稱(chēng)為主XML索引。通過(guò)它,可以創(chuàng )建三種類(lèi)型的二級XML索引提高查詢(xún)速度,如下所述: 主XML索引 它將在XML列上索引XML實(shí)例的所有標簽(tags)、值和路徑?;恚ㄒ簿褪怯蠿ML列的表)的主鍵必須是聚集索引。主鍵被用來(lái)關(guān)聯(lián)索引行和基表中的行??梢詮腦ML列中檢索完整的XML實(shí)例(舉例來(lái)說(shuō),SELECT *)。使用主XML索引的查詢(xún)返回標量值或XML子樹(shù)。 例:創(chuàng )建主XML索引 我們將在大多數例子中以表T(pk INT PRIMARY KEY, xCol XML)為例,它有一個(gè)無(wú)類(lèi)型的XML列,通過(guò)簡(jiǎn)單的方法可以被擴展為有類(lèi)型的XML。為了更容易理解,被查詢(xún)的XML實(shí)例如下: <book genre="security" publicationdate="2002" ISBN="0-7356-1588-2"> <title>Writing Secure Code</title> <author> <first-name>Michael</first-name> <last-name>Howard</last-name> </author> <author> <first-name>David</first-name> <last-name>LeBlanc</last-name> </author> <price>39.99</price> </book> 下面的語(yǔ)句在表T的XML列xCol上創(chuàng )建了XML索引idx_xCol: CREATE PRIMARY XML INDEX idx_xCol on T (xCol) 二級XML索引 一旦主XML索引被建立,你便可以創(chuàng )建二級XML索引來(lái)針對不同查詢(xún)提高速度,有三種類(lèi)型的二級索引:路徑、屬性、值分別能提高基于路徑的查詢(xún)、定制屬性管理、基于值的查詢(xún)速度。路徑索引針對列中所有XML實(shí)例按照每個(gè)XML節點(diǎn)在文檔中的順序構建一個(gè)B+-樹(shù)(路徑,值)。屬性索引創(chuàng )建一個(gè)聚集的B+-數在(主鍵,路徑,值)上,值索引和路徑索引類(lèi)似,但其創(chuàng )建的B+-樹(shù)是在(值,路徑)上的。 下面是一些創(chuàng )建二級索引的指南: ·如果你經(jīng)常在XML列上使用路徑表達式,路徑二級索引將會(huì )很有用,最常用的案例是在T-SQL的where子句中對XML列使用exist()方法。 ·如果你需要使用路徑表達式從單個(gè)XML實(shí)例中檢索多個(gè)值,屬性二級索引中的聚集路徑將會(huì )對此有幫助,通常在屬性包場(chǎng)景中有這種情況,某個(gè)對象的屬性被提取,而它的主鍵值是已知的。 ·如果你的工作需要查詢(xún)XML實(shí)例中的值,但你并不知道包含值的元素或是屬性名稱(chēng),你可能想為此創(chuàng )建值索引。這種情況通常發(fā)生在有后代(descendant axes)的查找上,諸如//author[last-name="Howard"],這里<author>元素可以是層次的在任何一個(gè)級別上。它也可能用在有通配符的查詢(xún)里,諸如/book [@* = "novel"],該查詢(xún)將為<book>元素查找值為"novel"的屬性。 例:基于路徑的查詢(xún) 假設有如下查詢(xún): SELECT pk, xCol FROM T WHERE xCol.exist (\‘/book[@genre = "novel"]\‘) = 1 路徑表達式 /book/@genre 和值"novel"對應路徑索引的關(guān)鍵字,因此,一個(gè)二級的XML路徑索引將會(huì )有用: CREATE XML INDEX idx_xCol_Path on T (xCol) USING XML INDEX idx_xCol FOR PATH 例:提取對象屬性 考慮下面這個(gè)查詢(xún),它從表中每一行檢索屬性"genre," "title," 和ISBN: SELECT xCol.value (\‘(/book/@genre)[1]\‘, \‘varchar(50)\‘), xCol.value (\‘(/book/title)[1]\‘, \‘varchar(50)\‘), xCol.value (\‘(/book/@ISBN)[1]\‘, \‘varchar(50)\‘) FROM T 下面創(chuàng )建的屬性索引對這個(gè)例子很有用: CREATE XML INDEX idx_xCol_Property on T (xCol) USING XML INDEX idx_xCol FOR PROPERTY 例:基于值的查詢(xún) 在下面的查詢(xún)里,后代或自身斜杠(//)指定了一個(gè)部分路徑,因此基于ISBN的值的查詢(xún)將會(huì )用到值索引: SELECT xCol FROM T WHERE xCol.exist (\‘//book[@ISBN = "1-8610-0157-6"]\‘) = 1 創(chuàng )建如下值索引: CREATE XML INDEX idx_xCol_Value on T (xCol) USING XML INDEX idx_xCol FOR VALUE 在XML列上的全文索引 你可以在XML列上創(chuàng )建全文索引,它將索引XML的值而忽略XML標記。屬性值是不能被全文索引的(因為它們被看作標記的一部份),元素標記被用做邊界符。你可以把XML索引和全文索引結合起來(lái)用在這些場(chǎng)合: ·首先,使用SQL 全文索引過(guò)濾出感興趣的XML值。 ·接著(zhù),使用XML索引查詢(xún)這些XML值。 |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:33:40 -- 例:結合XML查詢(xún)的全文搜索 一旦全文索引被創(chuàng )建在XML列上,下面的查詢(xún)將檢查書(shū)的標題中的XML值是否包含"custom"詞: SELECT * FROM T WHERE CONTAINS(xCol,\‘custom\‘) AND xCol.exist(\‘/book/title/text()[contains(.,"custom")]\‘) =1 CONTAINS()方法將使用全文索引找出XML文檔中包含"custom"詞的XML值的子集,接著(zhù),exist()子句確保"custom"詞是在書(shū)的標題中出現而不是別處。 全文索引使用的CONTAINS()和XQuery的contains()有著(zhù)不同的語(yǔ)法。后者用于子串匹配,而前者使用單詞多形態(tài)(word stemming)來(lái)進(jìn)行記號(token)匹配。例如,如果搜索標題中的字符串"run",那么,"run", "runs," 和 "running"都匹配,因為全文索引的CONTAINS()和XQuery的contains()都被滿(mǎn)足。然而,如果標題中有"customizable"詞,那么上面的查詢(xún)則不匹配(全文索引的CONTAINS()失敗,但是XQuery的contains()成功)。一般來(lái)說(shuō),對于純粹的子串匹配,應該將全文索引的CONTAINS()去掉。 此外,全文搜索使用單詞多形態(tài),而XQuery的contains()是文字匹配。下面的例子說(shuō)明了它們之間的區別。 例:使用多形態(tài)全文搜索XML值 上個(gè)例子中的XQuery的contains()一般來(lái)說(shuō)不能別去掉,考慮下面的查詢(xún): SELECT * FROM T WHERE CONTAINS(xCol,\‘run\‘) 文檔中"ran"這個(gè)詞因為滿(mǎn)足多形態(tài)的關(guān)系匹配搜索條件。此外,該查詢(xún)也沒(méi)有用XQuery來(lái)檢查搜索文本。 當使用AXSD分解XML到有全文索引的關(guān)系型列上,對XML視圖的XPath查詢(xún)并不在基表上執行全文搜索。 Property Promotion 如果查詢(xún)主要用于查找較少的元素和屬性的值(如,基于customer id查找客戶(hù),/Customer/@CustId的值已被指定),你可以提升(promote)這些值到關(guān)系型的列中,這對于那些從整個(gè)XML實(shí)例中檢索小部分XML數據的查詢(xún)有一定幫助。此時(shí)創(chuàng )建XML索引顯得牛刀殺雞,相反,僅需對提升的列加索引即可。查詢(xún)必須被寫(xiě)成使用提升列才行(也就是,查詢(xún)優(yōu)化器并不能把XML列上的查詢(xún)重定向到提升列上)。 提升列可以是在同一個(gè)表的計算列或另一個(gè)表的用戶(hù)維護的列,這對于從每個(gè)XML實(shí)例中提升單個(gè)值是足夠了(也就是說(shuō)單值屬性),然而,對于多值屬性,你必須為其創(chuàng )建一個(gè)單獨的表,如下所示: 基于XML數據類(lèi)型的計算列 計算列可以用含XML數據類(lèi)型方法的用戶(hù)自定義函數來(lái)創(chuàng )建。這種類(lèi)型的計算列可以是任何SQL類(lèi)型,包括XML類(lèi)型。如下所示: 例:基于XML數據類(lèi)型方法的計算列 首先為書(shū)的ISBN創(chuàng )建用戶(hù)自定義函數: CREATE FUNCTION udf_get_book_ISBN (@xData xml) RETURNS varchar(20) BEGIN DECLARE @ISBN varchar(20) SELECT @ISBN = @xData.value(\‘/book[1]/@ISBN\‘, \‘varchar(20)\‘) RETURN @ISBN END 接著(zhù)在表中為ISBN增加一個(gè)計算列: ALTER TABLE T ADD 計算列可以用常規方式來(lái)添加索引。 例:針對該計算列的查詢(xún) 為了查找出ISBN為0-7356-1588-2的<book>,查詢(xún)如下: SELECT xCol FROM T WHERE xCol.exist (\‘/book[@ISBN = "0-7356-1588-2"]\‘) = 1 如果使用計算列,查詢(xún)如下: SELECT xCol FROM T WHERE ISBN = \‘0-7356-1588-2\‘ 你可以創(chuàng )建用戶(hù)自定義函數來(lái)返回XML數據類(lèi)型,也可以使用UDF返回計算列,但你不能在計算列上創(chuàng )建XML索引。 創(chuàng )建屬性表 你可能希望能夠提升一些XML數據中的多值屬性到一個(gè)或多個(gè)表中,為其創(chuàng )建索引,重定向查詢(xún)來(lái)使用它們。典型的應用場(chǎng)景是一些小數量的屬性查找卻耗費了大量的查詢(xún)資源。你可以這么做: ·創(chuàng )建一個(gè)或多個(gè)表來(lái)存放多值屬性。你可能會(huì )發(fā)現每個(gè)表存放一個(gè)屬性會(huì )更便利,在每個(gè)屬性表中復制基表的主鍵以便和基表相連。 ·如果你希望維護屬性的順序,你需要為其引進(jìn)一個(gè)單獨的列。 ·可以在XML列上創(chuàng )建觸發(fā)器來(lái)維護屬性表,在觸發(fā)器中,實(shí)現下面功能: ·使用XML數據類(lèi)型方法,諸如nodes() 和 value(),來(lái)向屬性表插入和刪除記錄。 ·在CLR中創(chuàng )建流表值(streaming table-valued)函數來(lái)向屬性表插入和刪除記錄。 ·針對屬性表采用SQL訪(fǎng)問(wèn)方式,針對基表XML列使用XML訪(fǎng)問(wèn)方式,用主鍵來(lái)連接它們。 例:創(chuàng )建一個(gè)屬性表 假設你希望提升authors的first name,書(shū)會(huì )有一個(gè)或多個(gè)作者,這樣first name是個(gè)多值屬性。每個(gè)first name被存在一個(gè)屬性表的不同行中?;淼闹麈I被復制到屬性表中用以向后連接。 create table tblPropAuthor (propPK int, propAuthor varchar(max)) 例:創(chuàng )建用戶(hù)自定義函數來(lái)從XML實(shí)例中生成記錄集 下面的表值函數udf_XML2Table接受一個(gè)主鍵值和一個(gè)XML實(shí)例,它檢索<book>元素所有作者的first name,并返回一個(gè)(主鍵,first name)記錄集。 create function udf_XML2Table (@pk int, @xCol xml) returns @ret_Table table (propPK int, propAuthor varchar(max)) with schemabinding as begin insert into @ret_Table select @pk, nref.value(\‘.\‘, \‘varchar(max)\‘) from @xCol.nodes(\‘/book/author/first-name\‘) R(nref) return end 例:創(chuàng )建觸發(fā)器來(lái)填充屬性表 Inserted觸發(fā)器:向屬性表中插入記錄 create trigger trg_docs_INS on T for insert as declare @wantedXML xml declare @FK int select @wantedXML = xCol from inserted select @FK = PK from inserted insert into tblPropAuthor select * from dbo.udf_XML2Table(@FK, @wantedXML) Delete觸發(fā)器:基于基表中要刪除行的主鍵值來(lái)刪除屬性表中的行 create trigger trg_docs_DEL on T for delete as declare @FK int select @FK = PK from deleted delete tblPropAuthor where propPK = @FK Update觸發(fā)器:根據被改寫(xiě)的XML實(shí)例刪除屬性表中存在的記錄,再插入新的記錄到屬性表中 create trigger trg_docs_UPD on T for update as if update(xCol) or update(pk) begin declare @FK int declare @wantedXML xml select @FK = PK from deleted delete tblPropAuthor where propPK = @FK select @wantedXML = xCol from inserted select @FK = pk from inserted insert into tblPropAuthor select * from dbo.udf_XML2Table(@FK, @wantedXML) end |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:34:38 -- 例:查找XML實(shí)例中first name為"David"的作者 查詢(xún)可以在XML列上操作,可供選擇的另一種方法是,可以在屬性列上查找,然后和基表相關(guān)聯(lián)返回一個(gè)XML實(shí)例,如: SELECT xCol FROM T JOIN tblPropAuthor ON T.pk = tblPropAuthor.propPK WHERE tblPropAuthor.propAuthor = \‘David\‘ 例:使用CLR流表值(streaming table-valued)函數 這種方法包括下面幾步:(a)定義一個(gè)CLR類(lèi)SqlReaderBase,它實(shí)現ISqlReader,并且通過(guò)在XML實(shí)例上應用路徑表達式生成流表值的輸出;(b)創(chuàng )建一個(gè)裝配件和T-SQL用戶(hù)自定義函數來(lái)調用CLR類(lèi);(c)定義insert, update, 和 delete觸發(fā)器維護屬性表。 首先,我們來(lái)創(chuàng )建流CLR函數,它的主干如下所示。XML數據類(lèi)型被暴露為ADO.NET中的一個(gè)受托管類(lèi),該類(lèi)支持CreateReader()方法,返回一個(gè)XmlReader。 public class c_streaming_xml_tvf {public static ISqlReader streaming_xml_tvf (SqlXml xmlDoc, string pathExpression) {return (new TestSqlReaderBase (xmlDoc, pathExpression)); } } // Class that implements ISqlReader public class TestSqlReaderBase : ISqlReader {XPathNodeIterator m_iterator; public SqlChars FirstName; // Metadata for current resultset private SqlMetaData[] m_rgSqlMetaData; public TestSqlReaderBase (SqlXml xmlDoc, string pathExpression) { // Variables for XPath navigation XPathDocument xDoc; XPathNavigator xNav; XPathExpression xPath; // Set sql meta data m_rgSqlMetaData = new SqlMetaData[1]; m_rgSqlMetaData[0] = new SqlMetaData ("FirstName", SqlDbType.NVarChar,50); //Set up the Navigator if (!xmlDoc.IsNull) xDoc = new XPathDocument (xmlDoc.CreateReader()); else xDoc = new XPathDocument (); xNav = xDoc.CreateNavigator(); xPath = xNav.Compile (pathExpression); m_iterator = xNav.Select(xPath); } public bool Read() {bool moreRows = true; if (moreRows = m_iterator.MoveNext()) FirstName = new SqlChars (m_iterator.Current.Value); return moreRows; } } 接下來(lái),創(chuàng )建一個(gè)裝配件和T-SQL用戶(hù)自定義函數SQL_streaming_xml_tvf和CLR函數streaming_xml_tvf相對應。用戶(hù)自定義函數被用來(lái)定義表值函數CLR_udf_XML2Table用以生成記錄集: create function CLR_udf_XML2Table (@pk int, @xCol xml) returns @ret_Table table (FK int, FirstName varchar(max)) with schemabinding as begin insert into @ret_Table select @pk, FirstName FROM SQL_streaming_xml_tvf (@xCol, \‘/book/author/first-name\‘) return end 最后,定義觸發(fā)器,用函數CLR_udf_XML2Table替代udf_XML2Table,這樣,insert觸發(fā)器如下: create trigger CLR_trg_docs_INS on T for insert as declare @wantedXML xml declare @FK int select @wantedXML = xCol from inserted select @FK = PK from inserted insert into tblPropAuthor select * from dbo.CLR_udf_XML2Table(@FK, @wantedXML) 刪除觸發(fā)器無(wú)需改變,改寫(xiě)觸發(fā)器僅僅需要把函數udf_XML2Table()替換為CLR_udf_XML2Table()即可。 XML架構集 一個(gè)XML架構集是一個(gè)元數據的實(shí)體,包含一個(gè)或多個(gè)相關(guān)的(例如通過(guò)<xs:import>)、也可以是不相關(guān)的XML架構。一個(gè)XML架構集中的單個(gè)XML架構通過(guò)其命名空間來(lái)識別。 可以用CREATE XML SCHEMA COLLECTION語(yǔ)法來(lái)創(chuàng )建XML架構集和提供一個(gè)或多個(gè)XML架構??梢韵蛞粋€(gè)已有的XML架構中添加X(jué)ML架構組件(component),也可以通過(guò)ALTER XML SCHEMA COLLECTION來(lái)向已有的XML架構集中添加架構。在SQL Server 2005中,XML架構集可以向任何SQL對象那樣使用安全模型來(lái)確保安全。 多類(lèi)型列 一個(gè)XML架構集C根據多個(gè)XML架構類(lèi)型化一個(gè)XML列xCol,加之標記DOCUMENT或CONTENT可以分別指定了是XML樹(shù)還是片斷被存儲在列xCol中。 對DOCUMENT來(lái)講,每個(gè)XML實(shí)例根據驗證和類(lèi)型指定了它的頂級元素的目標命名空間,另一方面,對CONTENT,每個(gè)頂級元素可以指定在C中的任何一個(gè)目標命名空間。XML實(shí)例依照其中的所有目標命名空間來(lái)驗證和類(lèi)型化。 架構進(jìn)化 XML架構集被用來(lái)類(lèi)型化列、變量和參數,它提供了一種XML架構進(jìn)化的機制。假設你要增加一個(gè)目標命名空間為BOOK-V1 XML架構到XML架構集C。一個(gè)使用C來(lái)類(lèi)型化的XML列xCol便可以存儲和BOOK-V1 架構相一致的XML數據。 假設一個(gè)應用程序希望用新的XML組件擴展XML架構,諸如復雜的類(lèi)型定義和頂級元素聲明,這些新的架構組件可以被添加到BOOK-V1 架構中,并不要求重新驗證xCol列中已存在的XML數據。 假設在稍后時(shí)候,這個(gè)應用程序希望提供一個(gè)XML架構的新版本,目標命名空間為BOOK-V2,這個(gè)XML架構可以被添加到C,XML列可以同時(shí)存儲BOOK-V1和BOOK-V2,XML列上的查詢(xún)和數據修改要和這些命名空間相一致。 用法 裝載xml數據 從SQL Server 2000傳輸XML數據到SQL Server 2005 你可以用多種方法傳輸XML數據到SQL Server 2005,下面這一段落我們將作些討論。 ·如果在你的SQL Server 2000數據庫中數據是在[n]text 或 image列,你可以使用DTS把表導入SQL Server 2005數據庫中,再使用ALTER TABLE命令把列的類(lèi)型改為XML。 ·你可以使用bcp out從SQL Server 2000中大容量拷貝數據出來(lái),再用bcp in大容量插入到SQL Server 2005數據庫中。 ·如果數據在SQL Server 2000中的關(guān)系型列中,那么創(chuàng )建一個(gè)帶ntext列的新表,也可以為該表增加一個(gè)主鍵列用于行標識。使用客戶(hù)端程序檢索由服務(wù)器通過(guò)FOR XML生成的XML數據,再把它寫(xiě)到ntext列中,接著(zhù)可以使用上面提到的技術(shù)傳輸數據到SQL Server 2005中。你也可以選擇直接寫(xiě)XML數據到SQL Server 2005的XML列中。 例:把列類(lèi)型改為XML 假設你希望把表R的XYZ列的類(lèi)型由[n]text 或image改為無(wú)類(lèi)型的XML,你可以用下面的命令: ALTER TABLE R ALTER COLUMN XYZ XML 如果需要,你可以指定一個(gè)XML架構集把類(lèi)型改為有類(lèi)型的XML。 大容量裝載(bulk load)XML數據 你可以使用SQL Server中大容量裝載功能把XML數據大容量裝載到服務(wù)器中,諸如使用bcp命令。OPENROWSET命令允許你從文件中裝載數據到XML列中,下面是一些相關(guān)的例子: 例:從文件裝載XML 這個(gè)例子說(shuō)明了如何往表T中插入一行,該行的值來(lái)自文件C:\\yukon\\xmlfile.xml,假設整型列的值為10: INSERT INTO T SELECT 10, xCol FROM (SELECT * FROM OPENROWSET (BULK \‘C:\\Yukon\\xmlfile.xml\‘, SINGLE_CLOB) AS xCol) AS R(xCol) 文本編碼 SQL Server 2005以Unicode(UTF-16)類(lèi)型存儲XML數據,從服務(wù)器被檢索的XML數據被編碼為UTF-16。如果你希望不同的編碼,你需要對檢索數據執行必要的轉換。有時(shí),你的XML數據可能有不同的編碼,那么在數據裝載時(shí)要小心: ·如果你的文本XML是Unicode (UCS-2, UTF-16)編碼,可以直接分配給XML列,變量,參數,不會(huì )有問(wèn)題。 ·如果編碼不是Unicode,并且是隱含的(和源代碼頁(yè)有關(guān)),數據庫中的字符串代碼頁(yè)應該和你希望裝載的代碼(如有必要,使用COLLATE)相同或兼容,如果不存在這樣的服務(wù)器代碼頁(yè),你應該用適當的編碼添加一個(gè)顯式的XML聲明。 ·使用顯式的編碼,或者使用varbinary()類(lèi)型(它和代碼頁(yè)無(wú)關(guān)),或者使用適當的代碼頁(yè)的字符串類(lèi)型,再分配數據到XML列,變量和參數。 例:顯式地指定編碼 假設你有一個(gè)XML文檔(vcdoc)被作為varchar(max)存儲,并沒(méi)有一個(gè)顯式的XML聲明。下面的語(yǔ)句用編碼"iso8859-1"增加一個(gè) XML聲明,連接X(jué)ML文檔,轉換結果為varbinary(max),以便字節表示被保留,最終被轉換為XML。這將使XML處理器根據指定的編碼"iso8859-1"解析數據,并為其生成對應的UTF-16表示值。 SELECT CAST( CAST ((\‘<?xml version="1.0" encoding="iso8859-1"?>\‘+ vcdoc) AS VARBINARY (MAX)) AS XML) Xquery和類(lèi)型推論(type inference) Xquery(http://www.w3.org/TR/xquery/)被嵌入T-SQL語(yǔ)言中以支持對XML數據類(lèi)型的查詢(xún)。該語(yǔ)言正由W |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:36:49 -- 錯誤模型 Xquery表達式和XML DML語(yǔ)句的語(yǔ)法錯誤將返回編譯錯誤。編譯階段檢查XQuery表達式和DML語(yǔ)句的靜態(tài)類(lèi)型正確性,并且對有類(lèi)型XML使用XML架構用于類(lèi)型推論。如果一個(gè)表達式由于類(lèi)型安全違反而導致運行時(shí)失敗,它將引發(fā)靜態(tài)類(lèi)型錯誤。一個(gè)這樣的例子是:增加字符串值到整型數據列中,或者查詢(xún)類(lèi)型數據中的一個(gè)不存在的節點(diǎn)。 和W 顯式轉換到正確的類(lèi)型將使用戶(hù)避免靜態(tài)錯誤,雖然運行錯誤將被轉換為空序列。 下面的子段落將詳細的討論類(lèi)型檢查。 單態(tài)(singleton)檢查 如果編譯器不能確定在運行時(shí)是否能保證一個(gè)單態(tài),那么諸如位置步驟、函數參數、操作符(例如eq)這些要求單態(tài)的都回返回一個(gè)錯誤。這種問(wèn)題經(jīng)常是由無(wú)類(lèi)型的數據而引起。例如,查詢(xún)一個(gè)attribute要求一個(gè)單態(tài)雙親元素,一個(gè)雙親節點(diǎn)的順序選擇就夠了。將node()-value()結合以提取attribute值可能并不要求順序的指定,就像下面的例子所示。 例:一個(gè)已知的單態(tài)在這個(gè)例子中,nodes()方法為每個(gè)<book>元素生成分離的行。value()方法對<book>節點(diǎn)求值,提取@genre的值,而@genre作為一個(gè)屬性,是一個(gè)單態(tài)。 FROM T CROSS APPLY xCol.nodes(\‘\‘//book\‘\‘) AS R(nref) 要注意,在類(lèi)型檢查時(shí),確保//first-name[1]和(//first-name)[1]的區別非常重要。前者返回一個(gè)<first-name>節點(diǎn)的序列,每個(gè)節點(diǎn)都是它同胞節點(diǎn)的最左邊<first-name>節點(diǎn),后者返回XML實(shí)例中的在文檔順序里的第一個(gè)單態(tài)<first-name>節點(diǎn)。 例:使用value() SELECT xCol.value(\‘\‘//author/last-name\‘\‘, \‘\‘nvarchar(50)\‘\‘) LastName FROM T 下面這個(gè)修正看起來(lái)不錯: SELECT xCol.value(\‘\‘//author/last-name[1]\‘\‘, \‘\‘nvarchar(50)\‘\‘) LastName FROM T 然而,因為在每一個(gè)XML實(shí)例中可能會(huì )有多個(gè)<author>節點(diǎn),其實(shí)它并沒(méi)有修正錯誤。下面的代碼是正確的: SELECT xCol.value(\‘\‘(//author/last-name)[1]\‘\‘, \‘\‘nvarchar(50)\‘\‘) LastName FROM T 該查詢(xún)返回每個(gè)XML實(shí)例中第一個(gè)<last-name>元素的值 雙親軸 如果一個(gè)節點(diǎn)的類(lèi)型不能被確定,它便成為anyType,它不能被隱式的轉換到任何別的類(lèi)型。這在使用雙親軸導航時(shí)最有可能發(fā)生(如xCol.query(\‘\‘/book/@genre/../price\‘\‘)),雙親節點(diǎn)類(lèi)型被確定為anyType。一個(gè)元素也可能被定義為anyType。在這些情況中,更多精確類(lèi)型信息的遺失常導致靜態(tài)類(lèi)型錯誤,并要求顯式的轉換原子值到它們的明確的類(lèi)型。 Data(),Text(), and String() AccessorsXQuery有函數fn:data()可以從節點(diǎn)中提取標量的,類(lèi)型化的值,對節點(diǎn)用text()返回文本節點(diǎn),函數fn:string()返回節點(diǎn)的字符串值。它們的用法有時(shí)會(huì )造成混淆,SQL Server 2005中對它們的使用指南如下,讓我們考慮有XML實(shí)例<age>12</age>: |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:37:48 -- 例:對XML數據類(lèi)型使用OpenXml() 我們可以用OpenXml()重寫(xiě)上面那個(gè)查詢(xún),通過(guò)創(chuàng )建一個(gè)游標,將每個(gè)XML實(shí)例讀到XML變量中,再對其應用OpenXml()。 DECLARE name_cursor CURSOR FOR SELECT xCol FROM T OPEN name_cursor DECLARE @xmlVal XML DECLARE @idoc int FETCH NEXT FROM name_cursor INTO @xmlVal WHILE (@@FETCH_STATUS = 0) BEGIN EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlVal SELECT * FROM OPENXML (@idoc, \‘\‘//author\‘\‘) WITH (FirstName varchar(50) \‘\‘first-name\‘\‘, LastName varchar(50) \‘\‘last-name\‘\‘) R WHERE R.FirstName != \‘\‘David\‘\‘ EXEC sp_xml_removedocument @idoc FETCH NEXT FROM name_cursor INTO @xmlVal END CLOSE name_cursor DEALLOCATE name_cursor OpenXml()創(chuàng )建了一個(gè)內存中的表述,并使用工作表來(lái)代替查詢(xún)處理器。它MSXML 3.0的XPath 1.0而不是XQuery引擎。工作表并不在對OpenXml()的多個(gè)調用間共享,即便是在同一個(gè)XML實(shí)例上,這樣限制了它的可擴展性。OpenXml()允許你訪(fǎng)問(wèn)邊緣表格式的XML數據(在不指定WITH子句時(shí)),它還允許你使用在一個(gè)分離的,"overflow"列中的剩余的XML值。 將nodes() 和 value()功能結合起來(lái)能更有效的使用XML索引。這樣,這種結合要比OpenXml具有更大的擴展性。 從行集中使用 FOR XML生成XML 你可以通過(guò)使用帶TYPE指示的FOR XML從行集中生成一個(gè)XML數據類(lèi)型實(shí)例。 結果可以被分配給一個(gè)XM數據類(lèi)型列,變量或者是參數,而且,FOR XML還能夠嵌套使用生成任何層次結構。這使得嵌套的FOR XML比FOR XML EXPLICIT要更方便書(shū)寫(xiě),但是它可能對深度層次性能不是很好。FOR XML也引入了一個(gè)新的PATH節點(diǎn),該節點(diǎn)指出了列的值在XML樹(shù)中的路徑。 新的FOR XML TYPE指示可以被用來(lái)定義在關(guān)系型數據上的只讀的XML視圖,該視圖可以用SQL 語(yǔ)句和嵌入的XQuery來(lái)查詢(xún),如下面的例子所示。例如,你可以在存儲過(guò)程中采用這樣的視圖。 例:返回XML數據類(lèi)型的SQL視圖 下面的SQL視圖定義創(chuàng )建了一個(gè)XML視圖,它基于一個(gè)關(guān)系型列(pk)和從一個(gè)XML列中檢索的作者: CREATE VIEW V (xmlVal) AS SELECT pk, xCol.query(\‘\‘/book/author\‘\‘) FROM T FOR XML AUTO, TYPE 視圖V包含一個(gè)單XML類(lèi)型列xmlVal,它可以象規則的XML數據類(lèi)型實(shí)例那樣被查詢(xún),例如,下面的查詢(xún)返回first name為“David”的作者: SELECT xmlVal.query(\‘\‘//author[first-name = "David"]\‘\‘) FROM V SQL視圖定義有點(diǎn)類(lèi)似于采用帶注解的架構創(chuàng )建的XML視圖,然而,它們之間存在重大的差別。SQL視圖定義是只讀的,并且必須用嵌入式XQuery來(lái)操作,這點(diǎn)和采用帶注解的架構創(chuàng )建的XML視圖差別很大,此外,SQL視圖在應用XQuery表達式之前物化(materializes)XML結果,而在XML視圖上的XPath查詢(xún)則估計為基表上的SQL查詢(xún)。 增加商業(yè)邏輯 可以用下面幾種方法增加商業(yè)邏輯到XML數據中: ·你可以通過(guò)寫(xiě)行、列約束來(lái)實(shí)現在插入和修改XML數據時(shí)的指定域的約束。 ·你可以在XML列上寫(xiě)觸發(fā)器,該觸發(fā)器在你插入和修改列值時(shí)激活,觸發(fā)器中可以包含指定域的驗證規則或填充屬性表。 ·你可以在你傳遞XML值的托管代碼中寫(xiě)SQLCLR函數,并使用System.Xml命名空間提供的XML處理能力。例如,可以對XML數據應用XSL轉換,象下面例子所示??晒┻x擇的方法還有反序列化XML到一個(gè)或多個(gè)托管類(lèi)中,并且使用托管代碼操作它。 ·你可以根據商業(yè)需要寫(xiě)T-SQL存儲過(guò)程和函數來(lái)調用對XML列的處理操作。 例:XSL轉換的應用考慮一下這個(gè)CLR函數TransformXml(),它接受一個(gè)XML數據類(lèi)型實(shí)例和一個(gè)存儲在文件中的的XSL轉換,應用這個(gè)轉換到XML數據,并且返回被轉換過(guò)的XML,該函數的主干如下(使用C#編寫(xiě)): |
| -- 作者:admin -- 發(fā)布時(shí)間:2005-10-21 21:38:42 -- 交叉域查詢(xún) 當你的數據既有關(guān)系型列也有XML數據類(lèi)型列時(shí),你可能想寫(xiě)的查詢(xún)既能處理關(guān)系型也能處理XML數據。例如,你可以使用FOR XML轉換關(guān)系型數據和XML列數據到一個(gè)XML數據類(lèi)型實(shí)例,再使用XQuery查詢(xún)它?;蛘叻催^(guò)來(lái),你可以從XML值生成行集,再用T-SQL查詢(xún)它。 一個(gè)更方便有效的方法是寫(xiě)交叉域查詢(xún),它在XQuery或者XML DML表達式中使用SQL 變量或列的值: ·你可以用sql:variable()在你的XQuery或XML DML表達式中使用SQL 變量的值。 ·你可以用sql:column()在你的XQuery或XML DML表達式中使用關(guān)系型列的值。 · 這種方法允許應用程序參數化查詢(xún),如下面例子所示。然而,sql:variable()和sql:column()并不允許XML和用戶(hù)自定義類(lèi)型。 例:使用sql:variable()的交叉域查詢(xún) 下面的查詢(xún)是例子:Example: queries on a computed column based on XML data type methods.的修改版,在這個(gè)版本中,所感興趣的ISBN通過(guò)SQL變量@isbn來(lái)傳遞,用sql:variable()來(lái)替換常量,該查詢(xún)可以被用來(lái)查找任何ISBN,而不僅僅是ISBN: 0-7356-1588-2。 DECLARE @isbn varchar(20) SET @isbn = \‘0-7356-1588-2\‘ SELECT xCol FROM T WHERE xCol.exist (\‘/book[@ISBN = sql:variable("@isbn")]\‘) = 1可以用類(lèi)似的方法使用Sql:column(),且能提供額外的好處:基于代價(jià)的查詢(xún)優(yōu)化器決定讓列上的索引使查詢(xún)更有效,此外,如在A computed column based on an XML data type.討論的那樣,計算列可以存儲提升的屬性。 原生XML支持的編目視圖 編目視圖用于提供關(guān)于XML使用的元數據信息,下面將討論它的一些特性。 XML索引 在編目視圖sys.indexes中的XML索引項的”type”列為3,”name”列則包含了XML索引的名字。 XML索引也記錄在編目視圖sys.xml_indexes中,它包含所有的sys.indexes列,并有一些專(zhuān)門(mén)用于XML索引的意義,在列”secondary_type”值NULL指明這是個(gè)主XML索引,值”P”,”R”,”V”分別代表二級索引的PATH,PROPERTY,VALUE。 XML索引的空間占用可以用表值函數sys.fn_indexinfo( )查看,它提供了一些信息諸如:磁盤(pán)空間占用量,平均每行占多少字節,記錄數,和一些所有索引類(lèi)型都有的其他信息,包括XML索引。這些信息對每個(gè)數據庫分區都可用。XML索引和基表使用同樣的分區架構和分區功能。 例:XML索引的空間使用SELECT sum(Pages) FROM sys.fn_indexinfo (\‘T\‘, \‘idx_xCol_Path\‘ , DEFAULT, \‘DETAILED\‘) 它將生成表T上的XML索引index idx_xCol_Path在所有分區的磁盤(pán)占用數,如果不用sum(),將返回每個(gè)分區的磁盤(pán)占用情況。 檢索XML架構集 XML架構集被存儲在編目視圖sys.xml_schema_collections中,XML架構集”sys”由系統定義,它包含預定義的命名空間可被用于所有用戶(hù)自定義的XML架構集中,無(wú)須顯式的裝載它們。它包含的命名空間有:xml, xs, xsi, fn, xdt。另外兩個(gè)值得提及的編目視圖是:sys.xml_schema_namespaces,它列舉了每個(gè)XML架構集的所有命名空間;sys.xml_components,它列舉了每個(gè)XML架構的組件。 系統內建的函數XML_SCHEMA_NAMESPACE (schemaName, XmlSchemacollectionName, namespace-uri)生成一個(gè)XML數據類(lèi)型實(shí)例,它包含XML架構集中的XML架構片斷,除了預定義的XML架構。 你可以列出用下面的方法列出XML架構集的內容:·對合時(shí)的XML架構集的編目視圖寫(xiě)T-SQL查詢(xún)。·使用內建的函數XML_SCHEMA_NAMESPACE()。你可以在這個(gè)函數的輸出上應用XML數據類(lèi)型方法,但你不能修改基XML架構。·下面有一些示例: 例:列出一個(gè)XML架構集中的命名空間對XML架構集”myCollection”使用下面的查詢(xún): SELECT XSN.name FROM sys.xml_schema_collections XSC JOIN sys.xml_schema_namespaces XSN ON (XSC.xml_collection_id = XSN.xml_collection_id) 例:列出一個(gè)XML架構集的內容下面的語(yǔ)句列出和架構dbo有關(guān)的XML架構集”myCollection”的內容 SELECT XML_SCHEMA_NAMESPACE (N\‘dbo\‘, N\‘myCollection\‘) 1 通過(guò)指定目標命名空間給XML_SCHEMA_NAMESPACE()的第三個(gè)參數,架構集中的單個(gè)XML架構可以被作為XML數據類(lèi)型實(shí)例來(lái)獲得,如下所示: 例:從一個(gè)XML架構集中輸出指定的架構下面的語(yǔ)句從XML架構集"myCollection"中輸出目標命名空間為“http://www.microsoft.com/books”的XML架構。 SELECT XML_SCHEMA_NAMESPACE (N\‘dbo\‘, N\‘myCollection\‘, N\‘http://www.microsoft.com/books\‘) |
聯(lián)系客服