MS SQL SERVER2005 XML 最佳實(shí)踐
SQL Server 2005 為 XML 數(shù)據(jù)處理提供了廣泛支持。可以將 XML 值以本機(jī)方式存儲(chǔ)在 xml 數(shù)據(jù)類型列中,后者可以根據(jù) XML 架構(gòu)的集合進(jìn)行類型化,也可以保持非類型化狀態(tài)。可以對(duì) XML 列創(chuàng)建索引。此外,通過使用 XQuery 和 XML DML 可支持精細(xì)的數(shù)據(jù)操作。XML DML 是針對(duì)數(shù)據(jù)修改的擴(kuò)展。
SQL Server 2000 和 SQLXML Web 版本提供了強(qiáng)大的 XML 數(shù)據(jù)管理功能。這些功能著重于關(guān)系數(shù)據(jù)和 XML 數(shù)據(jù)之間的映射。可以使用帶批注的 XSD (AXSD) 來定義關(guān)系數(shù)據(jù)的 XML 視圖,以提供以 XML 為中心的方法,該方法支持對(duì) XML 數(shù)據(jù)執(zhí)行大容量數(shù)據(jù)加載、查詢和更新功能。Transact-SQL 擴(kuò)展提供了一個(gè)以 SQL 為中心的方法,以便使用 FOR XML 將關(guān)系查詢結(jié)果映射到 XML,以及使用 OPENXML 從 XML 生成關(guān)系視圖。這些支持已在 SQL Server 2005 中進(jìn)行了擴(kuò)展。結(jié)合新添加的本機(jī) XML 支持,SQL Server 2005 提供了一個(gè)強(qiáng)大的平臺(tái),以針對(duì)半結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)管理開發(fā)功能豐富的應(yīng)用程序。
本主題提供了 SQL Server 2005 中的 XML 數(shù)據(jù)建模和使用準(zhǔn)則,包含下列兩個(gè)部分:
數(shù)據(jù)建模
可以通過使用本機(jī) xml 數(shù)據(jù)類型和拆分到表中的 XML,以多種方式在 SQL Server 2005 中存儲(chǔ) XML 數(shù)據(jù)。本主題提供了為對(duì) XML 數(shù)據(jù)進(jìn)行建模做出適當(dāng)選擇的準(zhǔn)則。另外,還介紹了對(duì) XML 數(shù)據(jù)創(chuàng)建索引、屬性提升和 XML 實(shí)例的類型化。
使用
本部分討論了與使用相關(guān)的主題,例如將 XML 數(shù)據(jù)加載到服務(wù)器和查詢編譯中的類型推理。本部分還解釋和區(qū)分了密切相關(guān)的功能,并就如何適當(dāng)使用這些功能提出了建議。這些均通過示例進(jìn)行了說明。
數(shù)據(jù)建模本部分概述了應(yīng)使用 SQL Server 2005 中的 XML 功能的理由,另外還提供了在本機(jī) XML 存儲(chǔ)和 XML 視圖技術(shù)之間進(jìn)行選擇的準(zhǔn)則,并給出了數(shù)據(jù)建模建議。
關(guān)系或 XML 數(shù)據(jù)模型如果您的數(shù)據(jù)是高度結(jié)構(gòu)化的,具有已知架構(gòu),則對(duì)于數(shù)據(jù)存儲(chǔ),關(guān)系模型可能最適用。SQL Server 提供了您可能需要的必要功能和工具。另一方面,如果結(jié)構(gòu)是半結(jié)構(gòu)化或非結(jié)構(gòu)化的或者未知的,則必須考慮對(duì)這類數(shù)據(jù)進(jìn)行建模。
如果您需要一個(gè)與平臺(tái)無關(guān)的模型,以便通過使用結(jié)構(gòu)和語義標(biāo)記來確保數(shù)據(jù)的可移植性,則 XML 是一個(gè)不錯(cuò)的選擇。此外,下列情況下,適于做此選擇:
您的數(shù)據(jù)為稀疏數(shù)據(jù),或您不了解數(shù)據(jù)的結(jié)構(gòu),或數(shù)據(jù)結(jié)構(gòu)將來可能會(huì)有重大變化。
您的數(shù)據(jù)體現(xiàn)的是包容層次結(jié)構(gòu)而不是在實(shí)體間的引用,并且可能是遞歸數(shù)據(jù)。
您的數(shù)據(jù)本身具有順序性。
您希望基于數(shù)據(jù)的結(jié)構(gòu)查詢數(shù)據(jù)或更新部分?jǐn)?shù)據(jù)。
如果上述條件均不滿足,則應(yīng)使用關(guān)系數(shù)據(jù)模型。例如,如果數(shù)據(jù)為 XML 格式,但應(yīng)用程序只是使用數(shù)據(jù)庫來存儲(chǔ)和檢索數(shù)據(jù),則只需要 [n]varchar(max) 列。將數(shù)據(jù)存儲(chǔ)在 XML 列中還有其他好處,包括讓引擎確定數(shù)據(jù)格式是否正確或有效,以及支持對(duì) XML 數(shù)據(jù)進(jìn)行精細(xì)查詢和更新。
在 SQL Server 2005 中存儲(chǔ) XML 數(shù)據(jù)的理由下面是一些使用 SQL Server 2005 中的本機(jī) XML 功能而不是在文件系統(tǒng)中管理 XML 數(shù)據(jù)的理由:
您希望以一種高效的事務(wù)處理方式來共享、查詢和修改 XML 數(shù)據(jù)。精細(xì)的數(shù)據(jù)訪問對(duì)于您的應(yīng)用程序而言很重要。例如,您可能需要提取 XML 文檔中的某些部分,或者您可能需要插入新的部分而不是替換整個(gè)文檔。
您有關(guān)系數(shù)據(jù)和 XML 數(shù)據(jù),希望在應(yīng)用程序中進(jìn)行關(guān)系數(shù)據(jù)和 XML 數(shù)據(jù)之間的互操作。
您需要語言支持,以便對(duì)于跨域應(yīng)用程序可以進(jìn)行查詢和數(shù)據(jù)修改。
您希望服務(wù)器能夠保證數(shù)據(jù)格式正確,并能夠視情況根據(jù) XML 架構(gòu)來驗(yàn)證您的數(shù)據(jù)。
您希望對(duì) XML 數(shù)據(jù)創(chuàng)建索引以實(shí)現(xiàn)高效的查詢處理和良好的可伸縮性,并使用一流查詢優(yōu)化器。
您希望對(duì) XML 數(shù)據(jù)進(jìn)行 SOAP、ADO.NET 和 OLE DB 訪問。
您希望使用數(shù)據(jù)庫服務(wù)器的管理功能來管理 XML 數(shù)據(jù)。例如,這可能是備份、恢復(fù)和復(fù)制。
如果上述條件均不滿足,最好將數(shù)據(jù)存儲(chǔ)為非 XML 大型對(duì)象類型,如 [n]varchar(max) 或 varbinary(max)。
XML 存儲(chǔ)選項(xiàng)SQL Server 2005 中的 XML 存儲(chǔ)選項(xiàng)包括:
采用 xml 數(shù)據(jù)類型的本機(jī)存儲(chǔ)
數(shù)據(jù)以保留數(shù)據(jù)的 XML 內(nèi)容的內(nèi)部表示形式進(jìn)行存儲(chǔ),XML 內(nèi)容包括包容層次結(jié)構(gòu)、文檔順序、元素和屬性值等。具體來說,就是保留 XML 數(shù)據(jù)的 InfoSet 內(nèi)容。有關(guān) InfoSet 的詳細(xì)信息,請(qǐng)?jiān)L問 http://www.w3.org/TR/xml-infoset。InfoSet 內(nèi)容并不是文本 XML 的精確副本,因?yàn)槠渲形幢A粝铝行畔ⅲ簾o關(guān)緊要的空格、屬性順序、命名空間前綴和 XML 聲明。
對(duì)于類型化的 xml 數(shù)據(jù)類型(即綁定到 XML 架構(gòu)的 xml 數(shù)據(jù)類型),后架構(gòu)驗(yàn)證 InfoSet (PSVI) 將類型信息添加到 InfoSet,并以內(nèi)部表示形式進(jìn)行編碼。這會(huì)顯著提高分析速度。有關(guān)詳細(xì)信息,請(qǐng)參閱 http://www.w3.org/TR/xmlschema-1 和 http://www.w3.org/TR/xmlschema-2 上的 W3C XML 架構(gòu)規(guī)范。
在 XML 和關(guān)系存儲(chǔ)之間映射
通過使用帶批注的架構(gòu) (AXSD),將 XML 分解到一個(gè)或多個(gè)表中的列。這可保留在關(guān)系級(jí)別上的數(shù)據(jù)保真度。因此,盡管忽略了元素間的順序,但仍保留了層次結(jié)構(gòu)。架構(gòu)不能是遞歸的。
大型對(duì)象存儲(chǔ) [n]varchar(max) 和 varbinary(max)
存儲(chǔ)數(shù)據(jù)的精確副本。這對(duì)于特殊用途的應(yīng)用(如法律文檔)很有用。大多數(shù)應(yīng)用不需要完全相同的副本,且 XML 內(nèi)容(InfoSet 保真度)即可滿足需要。
通常,您必須結(jié)合使用這些方法。例如,您可能需要將 XML 數(shù)據(jù)存儲(chǔ)在 xml 數(shù)據(jù)類型列中,并將其中的屬性提升到關(guān)系列中。或者,您可能需要使用映射技術(shù)將非遞歸部分存儲(chǔ)到非 XML 列中,而只將遞歸部分存儲(chǔ)在 xml 數(shù)據(jù)類型列中。
XML 技術(shù)的選擇XML 技術(shù)(本機(jī) XML 與 XML 視圖)的選擇通常取決于下列因素:
存儲(chǔ)選項(xiàng)
您的 XML 數(shù)據(jù)可能更適于大型對(duì)象存儲(chǔ)(例如,產(chǎn)品手冊(cè)),或更適于存儲(chǔ)在關(guān)系列中(例如,轉(zhuǎn)換為 XML 的行項(xiàng))。每個(gè)存儲(chǔ)選項(xiàng)都在不同程度上保留文檔保真度。
查詢功能
您可能會(huì)發(fā)現(xiàn),基于查詢的特性和對(duì) XML 數(shù)據(jù)進(jìn)行查詢的程度,某一個(gè)存儲(chǔ)選項(xiàng)比其他選項(xiàng)更合適。在兩個(gè)存儲(chǔ)選項(xiàng)中,對(duì) XML 數(shù)據(jù)的精細(xì)查詢(例如,XML 節(jié)點(diǎn)上的謂詞評(píng)估)得到不同程度的支持。
對(duì) XML 數(shù)據(jù)創(chuàng)建索引
您可能希望對(duì) XML 數(shù)據(jù)創(chuàng)建索引以提高 XML 查詢的性能。索引選項(xiàng)隨存儲(chǔ)選項(xiàng)的不同而不同,您必須做出適當(dāng)?shù)倪x擇才能優(yōu)化工作負(fù)荷。
數(shù)據(jù)修改功能
某些工作負(fù)荷涉及對(duì) XML 數(shù)據(jù)進(jìn)行精細(xì)修改。例如,在文檔中添加新的部分,而其他工作負(fù)荷(如 Web 內(nèi)容)則不涉及。對(duì)于您的應(yīng)用程序來說,數(shù)據(jù)修改語言支持可能很重要。
架構(gòu)支持
您的 XML 數(shù)據(jù)可通過架構(gòu)進(jìn)行說明,該架構(gòu)可能是 XML 架構(gòu)文檔,也可能不是。對(duì)架構(gòu)綁定的 XML 的支持取決于 XML 技術(shù)。
此外,不同的選擇具有不同的性能特征。
本機(jī) XML 存儲(chǔ)您可以將 XML 數(shù)據(jù)存儲(chǔ)在服務(wù)器上的 xml 數(shù)據(jù)類型列中。下列情況下,適于做此選擇:
您希望使用一種簡(jiǎn)單的方法將 XML 數(shù)據(jù)存儲(chǔ)在服務(wù)器上,同時(shí)保留文檔順序和文檔結(jié)構(gòu)。
您可能有對(duì)應(yīng)于您的 XML 數(shù)據(jù)的架構(gòu),也可能沒有。
您希望查詢和修改 XML 數(shù)據(jù)。
您希望對(duì) XML 數(shù)據(jù)創(chuàng)建索引,以提高查詢處理的速度。
您的應(yīng)用程序需要系統(tǒng)目錄視圖以管理您的 XML 數(shù)據(jù)和 XML 架構(gòu)。
如果您的 XML 文檔具有多種結(jié)構(gòu),或您的 XML 文檔符合不同的或復(fù)雜的架構(gòu),而這些架構(gòu)很難映射到關(guān)系結(jié)構(gòu),本機(jī) XML 存儲(chǔ)很有用。
示例:使用 xml 數(shù)據(jù)類型對(duì) XML 數(shù)據(jù)進(jìn)行建模例如有一個(gè) XML 格式的產(chǎn)品手冊(cè),其中每個(gè)主題對(duì)應(yīng)單獨(dú)的一章,而每章中又包含多節(jié)。一節(jié)可以包含多個(gè)小節(jié)。因此,<section> 是一個(gè)遞歸元素。產(chǎn)品手冊(cè)包含大量混合內(nèi)容、關(guān)系圖和技術(shù)材料;數(shù)據(jù)是半結(jié)構(gòu)化的。用戶可能希望對(duì)感興趣的主題執(zhí)行上下文搜索,例如,在有關(guān)“索引”的章中搜索有關(guān)“聚集索引”的節(jié),并查詢技術(shù)數(shù)量。
適于您的 XML 文檔的存儲(chǔ)模型是 xml 數(shù)據(jù)類型列。這可保留 XML 數(shù)據(jù)的 InfoSet 內(nèi)容。對(duì) XML 列創(chuàng)建索引有利于提高查詢性能。
示例:保留 XML 數(shù)據(jù)的精確副本為了進(jìn)行說明,假定政府條例要求您保留 XML 文檔的精確文本副本。例如,這些文檔可能為簽署的文檔、法律文檔或股票交易單。您可能希望將文檔存儲(chǔ)在 [n]varchar(max) 列中。
查詢時(shí),先在運(yùn)行時(shí)將數(shù)據(jù)轉(zhuǎn)換為 xml 數(shù)據(jù)類型,然后對(duì)其執(zhí)行 Xquery。運(yùn)行時(shí)轉(zhuǎn)換開銷可能很高,尤其是在文檔較大的情況下。如果經(jīng)常查詢,可以采取冗余方式將文檔存儲(chǔ)在 xml 數(shù)據(jù)類型列中,并對(duì)其創(chuàng)建索引,同時(shí)從 [n]varchar(max) 列中返回精確的文檔副本。
XML 列可以是基于 [n]varchar(max) 列的計(jì)算列。但不能對(duì) XML 計(jì)算列創(chuàng)建 XML 索引,也不能對(duì) [n]varchar(max) 或 varbinary(max) 列創(chuàng)建 XML 索引。
XML 視圖技術(shù)通過定義 XML 架構(gòu)和數(shù)據(jù)庫中的表之間的映射,可以創(chuàng)建持久性數(shù)據(jù)的“XML 視圖”。通過 XML 視圖,可使用 XML 大容量加載來填充基礎(chǔ)表。您可以使用 XPath 1.0 版來查詢 XML 視圖;這種查詢將被轉(zhuǎn)換為針對(duì)表的 SQL 查詢。與此類似,更新也會(huì)被傳播到那些表。
在下列情況下,此技術(shù)很有用:
您希望擁有以 XML 為中心的編程模型,該模型使用現(xiàn)有關(guān)系數(shù)據(jù)上的 XML 視圖。
您有對(duì)應(yīng)于您的 XML 數(shù)據(jù)的架構(gòu)(XSD、XDR),該架構(gòu)可能由外部伙伴提供。
數(shù)據(jù)中的順序并不重要,或查詢表數(shù)據(jù)不是遞歸的,或事先已知最大遞歸深度。
您希望使用 XPath 1.0 版通過 XML 視圖查詢和修改數(shù)據(jù)。
您希望通過 XML 視圖來大容量加載 XML 數(shù)據(jù),并將其分解到基礎(chǔ)表。
相關(guān)示例包括顯示為用于數(shù)據(jù)交換和 Web 服務(wù)的 XML 的關(guān)系數(shù)據(jù)。有關(guān)詳細(xì)信息,請(qǐng)參閱 MSDN Online Library。
示例:使用帶批注的 XML 架構(gòu) (AXSD) 對(duì)數(shù)據(jù)進(jìn)行建模為了進(jìn)行說明,假定您具有希望將其作為 XML 處理的關(guān)系數(shù)據(jù)(如客戶、訂單和行項(xiàng))。請(qǐng)使用 AXSD 在關(guān)系數(shù)據(jù)上定義 XML 視圖。通過使用 XML 視圖可以將 XML 數(shù)據(jù)大容量加載到表,以及使用 XML 視圖查詢和更新關(guān)系數(shù)據(jù)。如果必須在 SQL 應(yīng)用程序不間斷工作時(shí)與其他應(yīng)用程序交換包含 XML 標(biāo)記的數(shù)據(jù),該模型很有用。
混合模型通常,對(duì)于數(shù)據(jù)建模,適于結(jié)合使用關(guān)系列和 xml 數(shù)據(jù)類型列。可以將 XML 數(shù)據(jù)中的某些值存儲(chǔ)在關(guān)系列中,而將其余或全部 XML 值存儲(chǔ)在 XML 列中。這可獲得更好的性能,您可以更好地控制對(duì)關(guān)系列創(chuàng)建的索引和鎖定特征。
要存儲(chǔ)在關(guān)系列中的值取決于您的工作負(fù)荷。例如,如果基于路徑表達(dá)式 /Customer/@CustId 檢索所有 XML 值,則將 CustId 屬性的值提升到關(guān)系列并對(duì)其創(chuàng)建索引可以獲得更快的查詢性能。另一方面,如果您的 XML 數(shù)據(jù)是以非冗余方式廣泛地分解為關(guān)系列中,則重新匯集的開銷可能很大。
對(duì)于高度結(jié)構(gòu)化的 XML 數(shù)據(jù),例如,表的內(nèi)容已轉(zhuǎn)換為 XML,您可以將所有值映射到關(guān)系列,并且可能使用 XML 視圖技術(shù)。
使用 xml 數(shù)據(jù)類型進(jìn)行數(shù)據(jù)建模本部分討論有關(guān)本機(jī) XML 存儲(chǔ)的數(shù)據(jù)建模主題,包括對(duì) XML 數(shù)據(jù)創(chuàng)建索引、屬性提升和類型化的 xml 數(shù)據(jù)類型。
相同或不同的表可以在包含其他關(guān)系列的表中,或在與主表具有外鍵關(guān)系的單獨(dú)表中創(chuàng)建 xml 數(shù)據(jù)類型列。
如果滿足下列條件之一,請(qǐng)?jiān)谕粋€(gè)表中創(chuàng)建 xml 數(shù)據(jù)類型列:
您的應(yīng)用程序?qū)?XML 列執(zhí)行數(shù)據(jù)檢索,并且不需要 XML 列的 XML 索引。
您希望對(duì) xml 數(shù)據(jù)類型列生成 XML 索引,并且主表的主鍵與其聚集鍵相同。有關(guān)詳細(xì)信息,請(qǐng)參閱“對(duì) xml 數(shù)據(jù)類型列創(chuàng)建索引”。
如果滿足下列條件,請(qǐng)?jiān)趩为?dú)的表中創(chuàng)建 xml 數(shù)據(jù)類型列:
您希望對(duì) xml 數(shù)據(jù)類型列生成 XML 索引,但主表的主鍵與其聚集鍵不同,或主表沒有主鍵,或主表是一個(gè)堆(即沒有聚集鍵)。如果主表已存在,可能會(huì)這樣。
您不希望因?yàn)楸碇写嬖?XML 列而降低表掃描的速度。無論該列是存儲(chǔ)在行內(nèi)還是行外,都會(huì)占用空間。
XML 數(shù)據(jù)的粒度XML 列中存儲(chǔ)的 XML 數(shù)據(jù)的粒度對(duì)鎖定至關(guān)重要,在一定程度上,對(duì)更新也很重要。SQL Server 對(duì) XML 數(shù)據(jù)和非 XML 數(shù)據(jù)都使用相同的鎖定機(jī)制。因此,行級(jí)鎖定會(huì)導(dǎo)致鎖定行中的所有 XML 實(shí)例。當(dāng)粒度較大時(shí),鎖定大型 XML 實(shí)例以便進(jìn)行更新會(huì)導(dǎo)致多用戶情況下的吞吐量下降。另一方面,過度分解會(huì)丟失對(duì)象封裝,并增加重新匯集開銷。
對(duì)于良好的設(shè)計(jì)而言,重要的是保持?jǐn)?shù)據(jù)建模要求與鎖定和更新特征之間的平衡。但在 SQL Server 2005 中,實(shí)際存儲(chǔ)的 XML 實(shí)例的大小并不十分重要。
例如,通過使用對(duì)部分二進(jìn)制大型對(duì)象 (BLOB) 和部分索引更新(將存儲(chǔ)的現(xiàn)有 XML 實(shí)例與其更新后的版本進(jìn)行比較)的新支持,對(duì) XML 實(shí)例進(jìn)行更新。部分二進(jìn)制大型對(duì)象 (BLOB) 更新在兩個(gè) XML 實(shí)例之間執(zhí)行差異比較,并只更新差異之處。部分索引更新只修改那些必須在 XML 索引中更改的行。
非類型化、類型化和約束的 xml 數(shù)據(jù)類型SQL Server 2005 xml 數(shù)據(jù)類型實(shí)現(xiàn)了 ISO SQL-2003 標(biāo)準(zhǔn) xml 數(shù)據(jù)類型。因此,它可以在非類型化的 XML 列中存儲(chǔ)格式正確的 XML 1.0 版的文檔、具有文本節(jié)點(diǎn)和任意數(shù)量頂級(jí)元素的所謂的 XML 內(nèi)容片段。系統(tǒng)將檢查數(shù)據(jù)格式是否正確,但不要求將列綁定到 XML 架構(gòu),并且拒絕在擴(kuò)展意義上格式不正確的數(shù)據(jù)。對(duì)于非類型化的 XML 變量和參數(shù)也是如此。
如果您有說明 XML 數(shù)據(jù)的 XML 架構(gòu),則可以將架構(gòu)與 XML 列相關(guān)聯(lián)以產(chǎn)生類型化的 XML。XML 架構(gòu)用于驗(yàn)證數(shù)據(jù),在編譯查詢和數(shù)據(jù)修改語句過程中執(zhí)行比非類型化的 XML 更精確的類型檢查,以及優(yōu)化存儲(chǔ)和查詢處理。
在下列情況下,請(qǐng)使用非類型化的 xml 數(shù)據(jù)類型:
您沒有對(duì)應(yīng)于您的 XML 數(shù)據(jù)的架構(gòu)。
您有架構(gòu),但不希望服務(wù)器驗(yàn)證數(shù)據(jù)。當(dāng)應(yīng)用程序在將數(shù)據(jù)存儲(chǔ)到服務(wù)器之前執(zhí)行客戶端驗(yàn)證時(shí),或臨時(shí)存儲(chǔ)根據(jù)架構(gòu)確定無效的 XML 數(shù)據(jù)時(shí),或在服務(wù)器上使用不受支持的架構(gòu)組件(如 key/keyref)時(shí),有時(shí)會(huì)出現(xiàn)這種情況。
在下列情況下,請(qǐng)使用類型化的 xml 數(shù)據(jù)類型:
您有對(duì)應(yīng)于您的 XML 數(shù)據(jù)的架構(gòu),并且希望服務(wù)器根據(jù) XML 架構(gòu)驗(yàn)證 XML 數(shù)據(jù)。
您希望充分利用基于類型信息的存儲(chǔ)和查詢優(yōu)化。
您希望在編譯查詢過程中更好地充分利用類型信息。
類型化的 XML 列、參數(shù)和變量可以存儲(chǔ) XML 文檔或內(nèi)容。但是,必須使用標(biāo)志指定在聲明時(shí)是存儲(chǔ)文檔還是存儲(chǔ)內(nèi)容。此外,必須提供 XML 架構(gòu)集合。如果每個(gè) XML 實(shí)例都剛好有一個(gè)頂級(jí)元素,請(qǐng)指定 DOCUMENT。否則,請(qǐng)使用 CONTENT。查詢編譯器在編譯查詢過程中的類型檢查中使用 DOCUMENT 標(biāo)志以推斷單一的頂級(jí)元素。
除了對(duì) XML 列進(jìn)行類型化之外,還可以對(duì)類型化或非類型化的 xml 數(shù)據(jù)類型列使用關(guān)系(列或行)約束。在下列情況下,請(qǐng)使用約束:
無法在 XML 架構(gòu)中表達(dá)業(yè)務(wù)規(guī)則。例如,花店的交貨地址必須在其營業(yè)地點(diǎn)周圍 50 英里之內(nèi)。這可以編寫為 XML 列的約束。約束可能涉及 xml 數(shù)據(jù)類型方法。
您的約束涉及表中的其他 XML 列或非 XML 列。例如,強(qiáng)制使 XML 實(shí)例中的客戶 ID (/Customer/@CustId) 與 CustomerID 關(guān)系列中的值匹配。
文檔類型定義 (DTD)可以使用 XML 架構(gòu)來對(duì) xml 數(shù)據(jù)類型列、變量和參數(shù)進(jìn)行類型化,但不能使用 DTD 進(jìn)行此項(xiàng)操作。但是,內(nèi)聯(lián) DTD 既可用于非類型化的 XML,也可用于類型化的 XML,以便提供默認(rèn)值,并將實(shí)體引用替換為其擴(kuò)展形式。
可以通過使用第三方工具將 DTD 轉(zhuǎn)換為 XML 架構(gòu)文檔,然后將 XML 架構(gòu)加載到數(shù)據(jù)庫中。
對(duì) xml 數(shù)據(jù)類型列創(chuàng)建索引可以對(duì) xml 數(shù)據(jù)類型列創(chuàng)建 XML 索引。它將對(duì)列中 XML 實(shí)例的所有標(biāo)記、值和路徑進(jìn)行索引,從而提高查詢性能。在下列情況下,您的應(yīng)用程序可以從 XML 索引中獲益:
對(duì) XML 列進(jìn)行查詢?cè)谀墓ぷ髫?fù)荷中很常見。必須考慮數(shù)據(jù)修改過程中的 XML 索引維護(hù)開銷。
XML 值相對(duì)較大,而檢索的部分相對(duì)較小。生成索引避免了在運(yùn)行時(shí)分析所有數(shù)據(jù),并且索引查找有利于進(jìn)行高效的查詢處理。
XML 列的第一個(gè)索引是主 XML 索引。使用它時(shí),可以對(duì) XML 列創(chuàng)建三種類型的輔助 XML 索引,以提供常見種類的查詢的速度,如以下部分所述。
主 XML 索引這將對(duì) XML 列中 XML 實(shí)例的所有標(biāo)記、值和路徑進(jìn)行索引。基表(即包含 XML 列的表)的主鍵必須具有聚集索引。主鍵用于將索引行與基表中的行相關(guān)聯(lián)。可從 XML 列中檢索完整的 XML 實(shí)例,例如 SELECT *。查詢使用主 XML 索引,并通過使用索引本身返回標(biāo)量值或 XML 子樹。
示例:創(chuàng)建主 XML 索引在大多數(shù)示例中,使用包含非類型化的 XML 列的表 T (pk INT PRIMARY KEY, xCol XML)。可以采用簡(jiǎn)單的方式將這些示例擴(kuò)展為類型化的 XML。有關(guān)如何使用類型化的 XML 的詳細(xì)信息,請(qǐng)參閱 xml 數(shù)據(jù)類型。為簡(jiǎn)化起見,針對(duì) XML 數(shù)據(jù)實(shí)例說明了查詢,如下所示:
復(fù)制代碼 <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>
以下語句對(duì)表 T 的 XML 列 xCol 創(chuàng)建 XML 索引(名為 idx_xCol):
復(fù)制代碼 CREATE PRIMARY XML INDEX idx_xCol on T (xCol)
輔助 XML 索引創(chuàng)建了主 XML 索引之后,您可能希望創(chuàng)建輔助 XML 索引來提高工作負(fù)荷中不同種類查詢的速度。三種類型的輔助 XML 索引(即 PATH、PROPERTY 和 VALUE)分別用于優(yōu)化基于路徑的查詢、自定義屬性管理方案和基于值的查詢。PATH 索引功能是按文檔順序?qū)α兄械乃?XML 實(shí)例生成各個(gè) XML 節(jié)點(diǎn)的 (path, value) 對(duì)的 B+ 樹。PROPERTY 索引功能是創(chuàng)建各個(gè) XML 實(shí)例中 (PK, path, value) 對(duì)的聚集 B+ 樹,其中 PK 是基表的主鍵。最后,VALUE 索引功能是按文檔順序?qū)?XML 列中的所有 XML 實(shí)例創(chuàng)建每個(gè)節(jié)點(diǎn)的 (value, path) 對(duì)的 B+ 樹。
下面是創(chuàng)建一個(gè)或多個(gè)這些索引的一些準(zhǔn)則:
如果工作負(fù)荷對(duì) XML 列大量使用路徑表達(dá)式,則 PATH 輔助 XML 索引可能會(huì)提高工作負(fù)荷的處理速度。最常見的情況是在 Transact-SQL 的 WHERE 子句中對(duì) XML 列使用 exist() 方法。
如果工作負(fù)荷通過使用路徑表達(dá)式從單個(gè) XML 實(shí)例中檢索多個(gè)值,則在 PROPERTY 索引中聚集各個(gè) XML 實(shí)例中的路徑可能會(huì)很有用。這種情況通常出現(xiàn)在屬性包方案中,此時(shí)提取對(duì)象的屬性并且已知其主鍵值。
如果工作負(fù)荷涉及查詢 XML 實(shí)例中的值,但不知道包含那些值的元素名稱或?qū)傩悦Q,則您可能希望創(chuàng)建 VALUE 索引。這通常出現(xiàn)在 descendant 軸查找中,例如 //author[last-name='Howard'],其中 <author> 元素可以出現(xiàn)在層次結(jié)構(gòu)的任何級(jí)別上。這種情況也出現(xiàn)在通配符查詢中,例如 /book [@* = 'novel'],其中查詢將查找具有某個(gè)值為“novel”的屬性的 <book> 元素。
示例:基于路徑的查找為了進(jìn)行說明,假定以下查詢?cè)谀墓ぷ髫?fù)荷中很常見:
復(fù)制代碼 SELECT pk, xColFROMTWHERE; xCol.exist ('/book/@genre[.='novel']') = 1
路徑表達(dá)式 /book/@genre 和值“novel”對(duì)應(yīng)于 PATH 索引的鍵字段。因此,PATH 類型的輔助 XML 索引對(duì)此工作負(fù)荷很有用:
復(fù)制代碼 CREATE XML INDEX idx_xCol_Path on T (xCol)USING XML INDEX idx_xCol FOR PATH
示例:提取對(duì)象的屬性例如,下面的查詢從表 T 中的各行檢索書的屬性 genre、title 和 ISBN:
復(fù)制代碼 SELECT xCol.value ('(/book/@genre)[1]', 'varchar(50)'),;xCol.value ('(/book/title/text())[1]', 'varchar(50)'),;xCol.value ('(/book/@ISBN)[1]', 'varchar(50)')FROM;T
在這種情況下,屬性索引很有用,其創(chuàng)建方式如下:
復(fù)制代碼 CREATE XML INDEX idx_xCol_Property on T (xCol)USING XML INDEX idx_xCol FOR PROPERTY
示例:基于值的查詢?cè)谙旅娴牟樵冎校琩escendant-or-self (//) 指定部分路徑,以便基于 ISBN 值的查找從 VALUE 索引的使用中獲益。
復(fù)制代碼 SELECT xColFROM;TWHERE;xCol.exist ('//book/@ISBN[. = '0-7356-1588-2']') = 1
VALUE 索引的創(chuàng)建方式如下:
復(fù)制代碼 CREATE XML INDEX idx_xCol_Value on T (xCol)USING XML INDEX idx_xCol FOR VALUE
對(duì) XML 列的全文索引您可以對(duì) XML 列創(chuàng)建一個(gè)全文索引,該索引對(duì) XML 值的內(nèi)容進(jìn)行索引,但忽略 XML 標(biāo)記。屬性值不在全文索引范圍內(nèi),因?yàn)樗鼈儽灰暈闃?biāo)記的一部分,并且元素標(biāo)記被用作標(biāo)記邊界。如有可能,可以按下列方式將全文搜索和 XML 索引結(jié)合起來:
首先,使用 SQL 全文搜索篩選感興趣的 XML 值。
然后,查詢那些使用 XML 列的 XML 索引的 XML 值。
示例:將全文搜索和 XML 查詢結(jié)合起來對(duì) XML 列創(chuàng)建了全文索引后,下面的查詢將檢查 XML 值是否在書的標(biāo)題中包含“custom”一詞:
復(fù)制代碼 SELECT * FROMT WHERE; CONTAINS(xCol,'custom') AND;xCol.exist('/book/title/text()[contains(.,'custom')]') =1
contains() 方法使用全文索引來將文檔中任何位置包含“custom”一詞的 XML 值組合為一個(gè)子集。exist() 子句確保“custom”一詞出現(xiàn)在書的標(biāo)題中。
使用 contains() 的全文搜索與 XQuery contains() 具有不同語義。后者是子字符串匹配,前者是使用詞干匹配的標(biāo)記匹配。因此,如果搜索標(biāo)題中包含“run”的字符串,則匹配結(jié)果將包括“run”、“runs”和“running”,因?yàn)橥瑫r(shí)滿足全文 contains() 和 Xquery contains()。但是,查詢不匹配標(biāo)題中的“customizable”一詞,因?yàn)槿?contains() 失敗,而滿足 Xquery contains()。通常,對(duì)于純子字符串匹配,應(yīng)刪除全文 contains() 子句。
此外,全文搜索使用詞干匹配,而 XQuery contains() 是文字匹配。這一區(qū)別在下一個(gè)示例中進(jìn)行說明。
示例:使用詞干匹配對(duì) XML 值進(jìn)行全文搜索通常不能消除上一個(gè)示例中執(zhí)行的 XQuery contains() 檢查。請(qǐng)看下面的查詢:
復(fù)制代碼 SELECT * FROMT WHERE; CONTAINS(xCol,'run')
因?yàn)槭褂昧嗽~干匹配,所以文檔中的“ran”一詞匹配搜索條件。此外,不通過使用 XQuery 來檢查搜索上下文。
當(dāng)通過使用 AXSD 將 XML 分解為全文索引的關(guān)系列時(shí),對(duì) XML 視圖執(zhí)行的 XPath 查詢不對(duì)基礎(chǔ)表執(zhí)行全文搜索。
屬性提升如果主要是對(duì)少數(shù)元素和屬性值進(jìn)行查詢,您可能希望將那些數(shù)量提升到關(guān)系列。檢索整個(gè) XML 實(shí)例,但只對(duì)一小部分 XML 數(shù)據(jù)進(jìn)行查詢時(shí),這很有用。不必對(duì) XML 列創(chuàng)建 XML 索引。但可以對(duì)提升的列創(chuàng)建索引。必須編寫查詢來使用提升的列。也就是說,查詢優(yōu)化器不會(huì)將對(duì) XML 列的查詢?cè)俣ㄏ虻教嵘牧小?/P>
提升的列可以是同一個(gè)表中的計(jì)算列,也可以是表中用戶維護(hù)的單獨(dú)列。從每個(gè) XML 實(shí)例提升單一值時(shí),這就足夠了。但是,對(duì)于多值屬性,則必須為屬性創(chuàng)建單獨(dú)的表,如以下部分所述。
基于 xml 數(shù)據(jù)類型的計(jì)算列可以使用調(diào)用 xml 數(shù)據(jù)類型方法的用戶定義函數(shù)來創(chuàng)建計(jì)算列。計(jì)算列的類型可以是任何 SQL 類型,包括 XML。下面的示例說明了這一點(diǎn)。
示例:基于 xml 數(shù)據(jù)類型方法的計(jì)算列為書的 ISBN 號(hào)創(chuàng)建用戶定義函數(shù):
復(fù)制代碼 CREATE FUNCTION udf_get_book_ISBN (@xData xml)RETURNS varchar(20)BEGINDECLARE @ISBNvarchar(20)SELECT @ISBN = @xData.value('/book[1]/@ISBN', 'varchar(20)')RETURN @ISBN END
在表中為 ISBN 添加計(jì)算列:
復(fù)制代碼 ALTER TABLE;;;TADDISBN AS dbo.udf_get_book_ISBN(xCol)
可以按通常的方式對(duì)計(jì)算列創(chuàng)建索引。
示例:對(duì)基于 xml 數(shù)據(jù)類型方法的計(jì)算列的查詢?nèi)粢@得其 ISBN 為 0-7356-1588-2 的 <book>:
復(fù)制代碼 SELECT xColFROMTWHERE; xCol.exist('/book/@ISBN[. = '0-7356-1588-2']') = 1
可以重新編寫對(duì) XML 列的查詢以使用計(jì)算列,如下所示:
復(fù)制代碼 SELECT xColFROMTWHERE; ISBN = '0-7356-1588-2'
您可以創(chuàng)建返回 xml 數(shù)據(jù)類型的用戶定義函數(shù),并使用用戶定義函數(shù)來創(chuàng)建計(jì)算列。但是,不能對(duì) XML 計(jì)算列創(chuàng)建 XML 索引。
創(chuàng)建屬性表您可能希望將 XML 數(shù)據(jù)中的某些多值屬性提升到一個(gè)或多個(gè)表中,對(duì)那些表創(chuàng)建索引,并再次定向查詢以使用這些表。典型的情況是少數(shù)屬性占了大部分查詢工作負(fù)荷。您可以執(zhí)行下列操作:
創(chuàng)建一個(gè)或多個(gè)表來保存多值屬性。您會(huì)發(fā)現(xiàn)可以很方便做到:每個(gè)表存儲(chǔ)一個(gè)屬性,以及在屬性表中復(fù)制基表的主鍵以便與基表進(jìn)行后向聯(lián)接。
如果希望維護(hù)屬性的相對(duì)順序,必須為相對(duì)順序引入一個(gè)單獨(dú)的列。
為 XML 列創(chuàng)建觸發(fā)器以維護(hù)屬性表。在觸發(fā)器中,執(zhí)行下列操作之一:
使用 xml 數(shù)據(jù)類型方法(如 nodes() 和 value())來插入和刪除屬性表的行。
在公共語言運(yùn)行時(shí) (CLR) 中創(chuàng)建流式表值函數(shù)來插入和刪除屬性表的行。
編寫對(duì)屬性表進(jìn)行 SQL 訪問的查詢和對(duì)基表中的 XML 列進(jìn)行 XML 訪問的查詢,這些表之間通過主鍵聯(lián)接起來。
示例:創(chuàng)建屬性表為了進(jìn)行說明,假定您希望提升作者的名字。書有一個(gè)或多個(gè)作者,因此名字為多值屬性。每個(gè)名字都存儲(chǔ)在屬性表的單獨(dú)行中。在屬性表中復(fù)制基表的主鍵以便進(jìn)行后向聯(lián)接。
復(fù)制代碼 create table tblPropAuthor (propPK int, propAuthor varchar(max))
示例:創(chuàng)建用戶定義函數(shù)以從 XML 實(shí)例生成行集以下表值函數(shù) udf_XML2Table 接受主鍵值和 XML 實(shí)例。它檢索 <book> 元素的所有作者的名字,然后返回主鍵-名字對(duì)行集。
復(fù)制代碼 create function udf_XML2Table (@pk int, @xCol xml)returns @ret_Table table (propPK int, propAuthor varchar(max))with schemabindingasbegin;;;insert into @ret_Table;;;;select @pk, nref.value('.', 'varchar(max)');;;[email protected]('/book/author/first-name') R(nref);;;returnend
示例:創(chuàng)建觸發(fā)器以填充屬性表插入觸發(fā)器將行插入屬性表:
復(fù)制代碼 create trigger trg_docs_INS on T for insertas;;;declare @wantedXML xml;;;declare @FK int;;;select @wantedXML = xCol from inserted;;;select @FK = PK from insertedinsert into tblPropAuthorselect * from dbo.udf_XML2Table(@FK, @wantedXML)
刪除觸發(fā)器根據(jù)刪除行的主鍵值刪除屬性表中的行:
復(fù)制代碼 create trigger trg_docs_DEL on T for deleteasdeclare @FK intselect @FK = PK from deleteddelete tblPropAuthor where propPK = @FK
更新觸發(fā)器根據(jù)更新的 XML 實(shí)例刪除屬性表中的現(xiàn)有行,然后將新行插入屬性表:
復(fù)制代碼 create trigger trg_docs_UPDon Tfor updateasif update(xCol) or update(pk)begin;;;declare @FK int;;;declare @wantedXML xml;;;select @FK = PK from deleted;;;delete tblPropAuthor where propPK = @FKselect @wantedXML = xCol from insertedselect @FK = pk from insertedinsert into tblPropAuthor;;;;select * from dbo.udf_XML2Table(@FK, @wantedXML)end
示例:查找其作者名字為“David”的 XML 實(shí)例可以對(duì) XML 列執(zhí)行查詢。此外,也可以在屬性表中搜索名字“David”,然后與基表進(jìn)行后向聯(lián)接以返回 XML 實(shí)例。例如:
復(fù)制代碼 SELECT xCol FROM;;T JOIN tblPropAuthor ON T.pk = tblPropAuthor.propPKWHERE;tblPropAuthor.propAuthor = 'David'
示例:使用 CLR 流式表值函數(shù)的解決方案此解決方案包括下列步驟:
定義 CLR 類 SqlReaderBase,它實(shí)現(xiàn) ISqlReader,并通過在 XML 實(shí)例上應(yīng)用路徑表達(dá)式來生成流式表值輸出。
創(chuàng)建程序集和 Transact-SQL 用戶定義函數(shù)來啟動(dòng)該 CLR 類。
通過使用用戶定義函數(shù)來定義插入、更新和刪除觸發(fā)器,以維護(hù)屬性表。
若要如此,首先創(chuàng)建流式 CLR 函數(shù)。xml 數(shù)據(jù)類型顯示為 ADO.NET 中的托管類 SqlXml,支持返回 XmlReader 的 CreateReader() 方法。
注意:; 本部分中的示例代碼使用了 XPathDocument 和 XPathNavigator。這些都強(qiáng)制要求您將所有 XML 文檔加載到內(nèi)存中。如果您要在您的應(yīng)用程序中使用類似代碼來處理多個(gè)大型 XML 文檔,此代碼并不可伸縮。而是應(yīng)盡可能保持較小的內(nèi)存分配并使用流式接口。有關(guān)性能的詳細(xì)信息,請(qǐng)參閱 Architecture of CLR Integration。
復(fù)制代碼 public class c_streaming_xml_tvf {public static ISqlReader streaming_xml_tvf (SqlXml xmlDoc, string pathExpression) {;;;return (new TestSqlReaderBase (xmlDoc, pathExpression));}}// Class that implements ISqlReaderpublic class TestSqlReaderBase : ISqlReader {XPathNodeIterator m_iterator;;public SqlChars FirstName;// Metadata for current resultsetprivate 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;}}
然后,創(chuàng)建程序集和與 CLR 函數(shù) streaming_xml_tvf 對(duì)應(yīng)的 Transact-SQL 用戶定義函數(shù) SQL_streaming_xml_tvf(不顯示)。該用戶定義函數(shù)用于定義表值函數(shù) CLR_udf_XML2Table 以便生成行集:
復(fù)制代碼 create function CLR_udf_XML2Table (@pk int, @xCol xml)returns @ret_Table table (FK int, FirstName varchar(max))with schemabindingasbegin;;;insert into @ret_Table;select @pk, FirstName;FROMSQL_streaming_xml_tvf (@xCol, '/book/author/first-name');;;returnend
最后,定義觸發(fā)器,如“創(chuàng)建觸發(fā)器以填充屬性表”示例中所示,但用 CLR_udf_XML2Table 函數(shù)替換了 udf_XML2Table。以下示例中顯示了插入觸發(fā)器:
復(fù)制代碼 create trigger CLR_trg_docs_INS on T for insertasdeclare @wantedXML xmldeclare @FK intselect @wantedXML = xCol from insertedselect @FK = PK from insertedinsert into tblPropAuthor;;;select *from;dbo.CLR_udf_XML2Table(@FK, @wantedXML)
刪除觸發(fā)器與非 CLR 版本相同。但是,更新觸發(fā)器只是用 CLR_udf_XML2Table() 函數(shù)替換了函數(shù) udf_XML2Table()。
XML 架構(gòu)集合XML 架構(gòu)集合是關(guān)系架構(gòu)作用域內(nèi)的元數(shù)據(jù)實(shí)體。它包含一個(gè)或多個(gè)可能相關(guān)(如通過 <xs:import>)也可能無關(guān)的 XML 架構(gòu)。XML 架構(gòu)集合中各個(gè) XML 架構(gòu)通過使用其目標(biāo)命名空間來標(biāo)識(shí)。
XML 架構(gòu)集合是通過使用 CREATE XML SCHEMA COLLECTION (Transact-SQL) 語法并提供一個(gè)或多個(gè) XML 架構(gòu)來創(chuàng)建。可以通過使用 ALTER XML SCHEMA COLLECTION (Transact-SQL) 語法,將多個(gè) XML 架構(gòu)組件添加到現(xiàn)有 XML 架構(gòu)中,并將多個(gè)架構(gòu)添加到 XML 架構(gòu)集合中。可以通過使用 SQL Server 2005 中的安全模式像任何 SQL 對(duì)象那樣保證 XML 架構(gòu)集合的安全。
多類型化列XML 架構(gòu)集合 C 根據(jù)多個(gè) XML 架構(gòu)對(duì) XML 列 xCol 進(jìn)行類型化。此外,DOCUMENT 標(biāo)志和 CONTENT 標(biāo)志指定是否可以將 XML 樹或片段分別存儲(chǔ)在 xCol 列中。
對(duì)于 DOCUMENT,每個(gè) XML 實(shí)例都指定實(shí)例中頂級(jí)元素的目標(biāo)命名空間,XML 實(shí)例根據(jù)它來進(jìn)行類型化和驗(yàn)證。另一方面,對(duì)于 CONTENT,每個(gè)頂級(jí)元素都可以指定 C 中任何一個(gè)目標(biāo)命名空間。XML 實(shí)例根據(jù)實(shí)例中存在的所有目標(biāo)命名空間來進(jìn)行驗(yàn)證和類型化。
架構(gòu)演變XML 架構(gòu)集合用于對(duì) XML 列、變量和參數(shù)進(jìn)行類型化。它提供了 XML 架構(gòu)演變的機(jī)制。為了進(jìn)行說明,假定您將具有目標(biāo)命名空間 BOOK-V1 的 XML 架構(gòu)添加到 XML 架構(gòu)集合 C 中。使用 C 類型化的 XML 列 xCol 可以存儲(chǔ)符合 BOOK-V1 架構(gòu)的 XML 數(shù)據(jù)。
然后,假定某個(gè)應(yīng)用程序希望用新的架構(gòu)組件(如復(fù)雜類型定義和頂級(jí)元素聲明)擴(kuò)展 XML 架構(gòu)。可以將這些新的架構(gòu)組件添加到 BOOK-V1 架構(gòu)中,并且不需要重新驗(yàn)證 xCol 列中的現(xiàn)有 XML 數(shù)據(jù)。
假定該應(yīng)用程序以后希望提供新版本的 XML 架構(gòu),并且它選擇目標(biāo)命名空間 BOOK-V2。可以將此 XML 架構(gòu)添加到 C 中。XML 列可以存儲(chǔ) BOOK-V1 和 BOOK-V2 的實(shí)例,并且可以對(duì)符合這些命名空間的 XML 實(shí)例執(zhí)行查詢和數(shù)據(jù)修改。
加載 XML 數(shù)據(jù)將 XML 數(shù)據(jù)從 SQL Server 2000 傳輸?shù)?SQL Server 2005您可以采用多種方式將 XML 數(shù)據(jù)傳輸?shù)?SQL Server 2005。例如:
如果將數(shù)據(jù)存儲(chǔ)在 SQL Server 2000 數(shù)據(jù)庫中的 [n]text 或 image 中,則可以使用 SQL Server Integration Services 將表導(dǎo)入 SQL Server 2005 數(shù)據(jù)庫中。使用 ALTER TABLE 語句將列類型更改為 XML。
可以使用 bcp out 從 SQL Server 2000 大容量復(fù)制數(shù)據(jù),然后使用 bcp in 將數(shù)據(jù)大容量插入 SQL Server 2005 數(shù)據(jù)庫中。
如果將數(shù)據(jù)存儲(chǔ)在 SQL Server 2000 數(shù)據(jù)庫的關(guān)系列中,請(qǐng)創(chuàng)建具有 [n]text 列和(可選)用于行標(biāo)識(shí)符的主鍵列的新表。使用客戶端編程檢索在服務(wù)器上通過 FOR XML 生成的 XML,并將其寫入 [n]text 列。然后,使用上述方法將數(shù)據(jù)傳輸?shù)?SQL Server 2005 數(shù)據(jù)庫中。您可以選擇將 XML 直接寫入 SQL Server 2005 數(shù)據(jù)庫中的 XML 列。
示例:將列類型更改為 XML假定您希望將 R 表中的 [n]text 列或 image 列 XYZ 的類型更改為非類型化的 XML。以下語句執(zhí)行此類型更改:
復(fù)制代碼 ALTER TABLE R ALTER COLUMN XYZ XML
如果需要,可以通過指定 XML 架構(gòu)集合將目標(biāo)為類型化為 XML。
大容量加載 XML 數(shù)據(jù)可以通過使用 SQL Server 的大容量加載功能(如 bcp)將 XML 數(shù)據(jù)大容量加載到服務(wù)器中。通過使用 OPENROWSET 可以將文件中的數(shù)據(jù)加載到 XML 列中。以下示例說明了這一點(diǎn)。
示例:從文件中加載 XML此示例顯示了如何在表 T 中插入行。從文件 C:MyFilexmlfile.xml 中將 XML 列的值作為 CLOB 加載,并為整數(shù)列提供了值 10。
復(fù)制代碼 INSERT INTO TSELECT 10, xColFROM;(SELECT *;;;;;FROM OPENROWSET (BULK 'C:MyFilexmlfile.xml', SINGLE_CLOB); AS xCol) AS R(xCol)
文本編碼SQL Server 2005 以 Unicode (UTF-16) 存儲(chǔ) XML 數(shù)據(jù)。從服務(wù)器檢索的 XML 數(shù)據(jù)均采用 UTF-16 編碼。如果需要采用不同的編碼,必須對(duì)檢索到的數(shù)據(jù)執(zhí)行所需的轉(zhuǎn)換。有時(shí),XML 數(shù)據(jù)可能采用不同的編碼。如果是這樣,加載數(shù)據(jù)時(shí)必須非常小心。例如:
如果文本 XML 采用 Unicode(UCS-2、UTF-16),可以將其賦給 XML 列、變量或參數(shù),不會(huì)有任何問題。
如果由于源代碼頁的原因,編碼不是 Unicode 而是隱式的,則數(shù)據(jù)庫中的字符串代碼頁應(yīng)與要加載的碼位相同或與其兼容。如果需要,請(qǐng)使用 COLLATE。如果不存在這樣的服務(wù)器代碼頁,則必須添加使用正確編碼的顯式 XML 聲明。
若要使用顯式編碼,請(qǐng)使用 varbinary() 類型(它與代碼頁沒有任何交互),或使用字符串類型的相應(yīng)代碼頁。然后,將數(shù)據(jù)賦給 XML 列、變量或參數(shù)。
示例:顯式指定編碼假定您有一個(gè) XML 文檔 vcdoc,它存儲(chǔ)為沒有顯式 XML 聲明的 varchar(max)。以下語句添加編碼為“iso8859-1”的 XML 聲明,將 XML 文檔串聯(lián)起來,將結(jié)果轉(zhuǎn)換為 varbinary(max) 以便保留字節(jié)表示形式,最終將其轉(zhuǎn)換為 XML。這樣,XML 處理器就可以根據(jù)指定的編碼“iso8859-1”分析數(shù)據(jù),并為字符串值生成相應(yīng)的 UTF-16 表示形式。
復(fù)制代碼 SELECT CAST( CAST (('<?xml version='1.0' encoding='iso8859-1'?>'+ vcdoc) AS VARBINARY (MAX)); AS XML)
XQuery 和類型推理Transact-SQL 中嵌入的 XQuery 語言支持查詢 xml 數(shù)據(jù)類型。該語言正在由萬維網(wǎng)聯(lián)盟 (W3C) 開發(fā),Microsoft 的所有主要數(shù)據(jù)庫供應(yīng)商都參與其中。它包含了 XPath 2.0 版作為導(dǎo)航語言。同時(shí),還提供了針對(duì) xml 數(shù)據(jù)類型的數(shù)據(jù)修改語言構(gòu)造。有關(guān) SQL Server 中支持的 XQuery 構(gòu)造、函數(shù)和運(yùn)算符的詳細(xì)信息,請(qǐng)參閱針對(duì) xml 數(shù)據(jù)類型的 XQuery 函數(shù)。
錯(cuò)誤模型語法不正確的 Xquery 表達(dá)式和 XML DML 語句會(huì)返回編譯錯(cuò)誤。編譯階段會(huì)檢查 XQuery 表達(dá)式和 DML 語句的靜態(tài)類型正確性,并針對(duì)類型化的 XML 使用 XML 架構(gòu)進(jìn)行類型推理。如果表達(dá)式在運(yùn)行時(shí)由于類型安全沖突而失敗,會(huì)引起靜態(tài)類型錯(cuò)誤。靜態(tài)錯(cuò)誤的示例包括將字符串添加到整數(shù),以及在不存在的節(jié)點(diǎn)中查詢類型化的數(shù)據(jù)。
與 W3C 標(biāo)準(zhǔn)有所不同的是,XQuery 運(yùn)行時(shí)錯(cuò)誤被轉(zhuǎn)換為空序列。這些序列根據(jù)調(diào)用上下文,可以作為空 XML 或 NULL 傳播到查詢結(jié)果。
通過顯式轉(zhuǎn)換為正確的類型,用戶可以解決靜態(tài)錯(cuò)誤的問題,盡管運(yùn)行時(shí)轉(zhuǎn)換錯(cuò)誤將被轉(zhuǎn)換為空序列。
下列部分詳細(xì)介紹了類型檢查。
單一性檢查如果編譯器無法確定是否在運(yùn)行時(shí)保證單一性,則要求單一性的位置步驟、函數(shù)參數(shù)和運(yùn)算符將返回錯(cuò)誤。此問題經(jīng)常出現(xiàn)在非類型化數(shù)據(jù)上。例如,對(duì)屬性的查找需要單一的父元素。選擇單個(gè)父節(jié)點(diǎn)的序號(hào)即可滿足需要。計(jì)算 node()-value() 組合以提取屬性值可能不需要指定序號(hào)。如以下示例中所示。
示例:已知單一性在此示例中,nodes() 方法為每個(gè) <book> 元素生成一個(gè)單獨(dú)的行。對(duì) <book> 節(jié)點(diǎn)進(jìn)行計(jì)算的 value() 方法提取 @genre 值,其作為屬性,具有單一性。
復(fù)制代碼 SELECT nref.value('@genre', 'varchar(max)') LastNameFROMT CROSS APPLY xCol.nodes('//book') AS R(nref)
XML 架構(gòu)用于對(duì)類型化的 XML 進(jìn)行類型檢查。如果某個(gè)節(jié)點(diǎn)指定為 XML 架構(gòu)中單一的節(jié)點(diǎn),則編譯器將使用該信息,并且不會(huì)發(fā)生任何錯(cuò)誤。否則,需要選擇單個(gè)節(jié)點(diǎn)的序號(hào)。特別的情況是,使用 descendant-or-self (//)(如在 /book//title 中)會(huì)丟失 <title> 元素的單一性基數(shù)推理,即使 XML 架構(gòu)指定其如此。因此,您應(yīng)該將其重寫為 (/book//title)[1]。
對(duì)于類型檢查,務(wù)必注意 //first-name[1] 和 (//first-name)[1] 之間的差異。前者返回一組 <first-name> 節(jié)點(diǎn),其中每個(gè)節(jié)點(diǎn)都是其同級(jí)節(jié)點(diǎn)間最左側(cè)的 <first-name> 節(jié)點(diǎn)。后者返回 XML 實(shí)例中按文檔順序的第一個(gè)單一的 <first-name> 節(jié)點(diǎn)。
示例:使用 value()下面對(duì)非類型化的 XML 列的查詢導(dǎo)致發(fā)生靜態(tài)的編譯錯(cuò)誤。這是因?yàn)?value() 希望將一個(gè)單一節(jié)點(diǎn)作為第一個(gè)參數(shù),而編譯器無法確定在運(yùn)行時(shí)是否將僅有一個(gè) <last-name> 節(jié)點(diǎn):
復(fù)制代碼 SELECT xCol.value('//author/last-name', 'nvarchar(50)') LastNameFROMT
可以考慮下面的解決辦法:
復(fù)制代碼 SELECT xCol.value('//author/last-name[1]', 'nvarchar(50)') LastNameFROMT
但是,該解決辦法不解決錯(cuò)誤,因?yàn)樵诿總€(gè) XML 實(shí)例中可能會(huì)有多個(gè) <author> 節(jié)點(diǎn)。采用下面的重寫代碼可以解決問題:
復(fù)制代碼 SELECT xCol.value('(//author/last-name/text())[1]', 'nvarchar(50)') LastNameFROMT
此查詢返回每個(gè) XML 實(shí)例中第一個(gè) <last-name> 元素的值。
parent 軸如果無法確定節(jié)點(diǎn)的類型,它將成為 anyType。這不會(huì)隱式轉(zhuǎn)換為任何其他類型。在使用 parent 軸(如 xCol.query('/book/@genre/../price'))進(jìn)行導(dǎo)航的過程中,尤其會(huì)發(fā)生這種情況。父節(jié)點(diǎn)類型確定為 anyType。在 XML 架構(gòu)中,也可以將元素定義為 anyType。在這兩種情況下,丟失更為精確的類型信息經(jīng)常會(huì)導(dǎo)致發(fā)生靜態(tài)類型錯(cuò)誤,并需要將原子值顯式轉(zhuǎn)換為其特定類型。
Data()、text() 和 string() 取值函數(shù)XQuery 有一個(gè)從節(jié)點(diǎn)提取類型化標(biāo)量值的函數(shù) fn:data()、一個(gè)返回文本節(jié)點(diǎn)的節(jié)點(diǎn)測(cè)試 text(),以及一個(gè)返回節(jié)點(diǎn)的字符串值的函數(shù) fn:string()。它們的用法容易混淆。以下是在 SQL Server 2005 中正確使用它們的準(zhǔn)則。使用 XML 實(shí)例 <age>12</age> 進(jìn)行說明。
非類型化的 XML:路徑表達(dá)式 /age/text() 返回文本節(jié)點(diǎn)“12”。函數(shù) fn:data(/age) 返回字符串值“12”,fn:string(/age) 也是如此。
類型化的 XML:對(duì)于任何簡(jiǎn)單的類型化的 <age> 元素,表達(dá)式 /age/text() 都返回靜態(tài)錯(cuò)誤。另一方面,fn:data(/age) 返回整數(shù) 12。fn:string(/age) 產(chǎn)生字符串“12”。
聯(lián)合類型的函數(shù)和運(yùn)算符由于類型檢查,聯(lián)合類型要求進(jìn)行小心地處理。下列示例中說明了其中兩個(gè)問題。
示例:聯(lián)合類型的函數(shù)例如,以下聯(lián)合類型的 <r> 的元素定義:
復(fù)制代碼 <xs:element name='r'><xs:simpleType><xs:union memberTypes='xs:int xs:float xs:double'/></xs:simpleType></xs:element>
在 XQuery 上下文中,“average”函數(shù) fn:avg (//r) 返回靜態(tài)錯(cuò)誤,因?yàn)?XQuery 編譯器無法對(duì) fn:avg() 的參數(shù)中的 <r> 元素的不同類型(xs:int、xs:float 或 xs:double)的值求和。為了解決此問題,請(qǐng)將函數(shù)調(diào)用重寫為 fn:avg(for $r in //r return $r cast as xs:double ?)。
示例:聯(lián)合類型的運(yùn)算符加法運(yùn)算(“+”)要求使用精確類型的操作數(shù)。因此,表達(dá)式 (//r)[1] + 1 返回靜態(tài)錯(cuò)誤,該錯(cuò)誤包含前面所述的 <r> 元素的類型定義。一個(gè)解決方法是將其重寫為 (//r)[1] cast as xs:int? +1,其中“?”表示取值 0 或 1。SQL Server 2005 要求帶有“?”的“cast as”,因?yàn)槿魏无D(zhuǎn)換都可能由于運(yùn)行時(shí)錯(cuò)誤導(dǎo)致產(chǎn)生空序列。
Value()、Nodes() 和 OpenXML()您可以在 SELECT 子句中對(duì) xml 數(shù)據(jù)類型使用多個(gè) value() 方法以生成所提取值的行集。nodes() 方法為可用于其他查詢的每個(gè)所選節(jié)點(diǎn)生成一個(gè)內(nèi)部引用。生成行集時(shí),如果行集有多個(gè)列且用于生成行集的路徑表達(dá)式比較復(fù)雜,結(jié)合使用 nodes() 和 value() 方法可能會(huì)更有效。
nodes() 方法生成特定 xml 數(shù)據(jù)類型的實(shí)例,每個(gè)實(shí)例的上下文都設(shè)置為不同的所選節(jié)點(diǎn)。這種 XML 實(shí)例支持 query()、value()、nodes() 和 exist() 方法,并可用于 count(*) 聚合。所有其他用法都會(huì)導(dǎo)致錯(cuò)誤。
示例:使用 nodes()假定您希望提取作者的名字和姓氏,而名字不是“David”。此外,您希望提取該信息作為一個(gè)包含兩列 FirstName 和 LastName 的行集。通過使用 nodes() 方法和 value() 方法便可以完成該操作,如下所示:
復(fù)制代碼 SELECT nref.value('(first-name/text())[1]', 'nvarchar(50)') FirstName,;;;;nref.value('(last-name/text())[1]', 'nvarchar(50)') LastNameFROMT CROSS APPLY xCol.nodes('//author') AS R(nref)WHERE; nref.exist('first-name[. != 'David']') = 1
在此示例中,nodes('//author') 生成一個(gè)由對(duì)每個(gè) XML 實(shí)例的 <author> 元素引用組成的行集。通過計(jì)算與那些引用相關(guān)的 value() 方法,即可獲得作者的名字和姓氏。
SQL Server 2000 提供了通過使用 OpenXml() 從 XML 實(shí)例生成行集的功能。您可以指定行集的關(guān)系架構(gòu),以及如何將 XML 實(shí)例中的值映射到行集中的列。
示例:對(duì) xml 數(shù)據(jù)類型使用 OpenXml()可以通過使用 OpenXml() 重寫上一個(gè)示例中的查詢,如下所示。方法是創(chuàng)建一個(gè)游標(biāo),該游標(biāo)將每個(gè) XML 實(shí)例讀取到 XML 變量,然后向其應(yīng)用 OpenXML:
復(fù)制代碼 DECLARE name_cursor CURSORFORSELECT xCol;FROMTOPEN name_cursorDECLARE @xmlVal XMLDECLARE @idoc intFETCH NEXT FROM name_cursor INTO @xmlValWHILE (@@FETCH_STATUS = 0)BEGINEXEC sp_xml_preparedocument @idoc OUTPUT, @xmlValSELECT*FROMOPENXML (@idoc, '//author'); WITH (FirstName; varchar(50) 'first-name',;;;;;LastNamevarchar(50) 'last-name') RWHERE; R.FirstName != 'David'EXEC sp_xml_removedocument @idocFETCH NEXT FROM name_cursor INTO @xmlValENDCLOSE name_cursorDEALLOCATE name_cursor
OpenXml() 創(chuàng)建一個(gè)內(nèi)存中的表示形式,并且使用工作表而不是查詢處理器。它依賴于 MSXML 3.0 版的 XPath 1.0 版處理器,而不是 XQuery 引擎。工作表不在對(duì) OpenXml() 的多個(gè)調(diào)用間共享(即使是在同一個(gè) XML 實(shí)例上)。這就限制了它的可伸縮性。在未指定 WITH 子句時(shí),可以通過 OpenXml() 訪問 XML 數(shù)據(jù)的邊緣表格式。另外,也可以通過它在單獨(dú)的“overflow”列中使用其余的 XML 值。
將 nodes() 和 value() 函數(shù)結(jié)合起來可有效地使用 XML 索引。因此,與 OpenXml 相比,這種結(jié)合有更高的可伸縮性。
使用 FOR XML 從行集生成 XML可以通過在 FOR XML 中使用新的 TYPE 指令,從行集生成 xml 數(shù)據(jù)類型實(shí)例。
可以將結(jié)果賦給 xml 數(shù)據(jù)類型列、變量或參數(shù)。另外,可以嵌套 FOR XML 以生成任何層次結(jié)構(gòu)。這使得嵌套的 FOR XML 比 FOR XML EXPLICIT 更容易編寫,但對(duì)于較深的層次結(jié)構(gòu),它的性能可能不太好。FOR XML 還引入了新的 PATH 模式。這個(gè)新模式指定某個(gè)列的值在 XML 樹中的路徑。
可以使用新的 FOR XML TYPE 指令,采用 SQL 語法來定義關(guān)系數(shù)據(jù)上的只讀 XML 視圖。可以使用 SQL 語句和嵌入式 XQuery 查詢?cè)撘晥D,如下面的示例所示。另外,您還可以在存儲(chǔ)過程中引用這些 SQL 視圖。
示例:返回生成的 xml 數(shù)據(jù)類型的 SQL 視圖以下 SQL 視圖定義對(duì)關(guān)系列 pk 和從 XML 列中檢索到的書作者創(chuàng)建 XML 視圖:
復(fù)制代碼 CREATE VIEW V (xmlVal) ASSELECT pk, xCol.query('/book/author')FROMTFOR XML AUTO, TYPE
V 視圖包含一個(gè)行,該行只有一個(gè) XML 類型的 columnxmlVal。可以查詢像常規(guī) xml 數(shù)據(jù)類型實(shí)例那樣對(duì)它進(jìn)行查詢。例如,下面的查詢返回名字為“David”的作者:
復(fù)制代碼 SELECT xmlVal.query('//author[first-name = 'David']')FROMV
SQL 視圖定義與使用帶批注的架構(gòu)創(chuàng)建的 XML 視圖有些相似。但二者之間存在重要的差異。SQL 視圖定義是只讀的,且必須使用嵌入式 XQuery 來操作。XML 視圖是通過使用帶批注的架構(gòu)創(chuàng)建的。此外,SQL 視圖在應(yīng)用 XQuery 表達(dá)式之前具體化 XML 結(jié)果,而對(duì) XML 視圖的 XPath 查詢是對(duì)基礎(chǔ)表計(jì)算 SQL 查詢。
添加業(yè)務(wù)邏輯可以采用多種方式將業(yè)務(wù)邏輯添加到 XML 數(shù)據(jù)中:
您可以編寫行或列約束,以在插入和修改 XML 數(shù)據(jù)時(shí)強(qiáng)制實(shí)施特定于域的約束。
您可以在 XML 列上編寫插入或更新列中的值時(shí)激發(fā)的觸發(fā)器。該觸發(fā)器可以包含特定于域的驗(yàn)證規(guī)則或填充屬性表。
您可以采用托管代碼編寫 SQLCLR 函數(shù)并將向其傳遞 XML 值,并且使用 System.Xml 命名空間提供的 XML 處理功能。例如,將 XSL 轉(zhuǎn)換應(yīng)用到 XML 數(shù)據(jù)。另外,您可以將 XML 反序列化為一個(gè)或多個(gè)托管類,并使用托管代碼對(duì)它們進(jìn)行操作。
您可以編寫 Transact-SQL 存儲(chǔ)過程和函數(shù),對(duì) XML 列進(jìn)行處理以滿足業(yè)務(wù)需要。
示例:應(yīng)用 XSL 轉(zhuǎn)換例如,CLR 函數(shù) TransformXml(),它接受 xml 數(shù)據(jù)類型實(shí)例和文件中存儲(chǔ)的 XSL 轉(zhuǎn)換,將轉(zhuǎn)換應(yīng)用到 XML 數(shù)據(jù),然后在結(jié)果中返回轉(zhuǎn)換的 XML。以下是用 C# 編寫的主干函數(shù):
復(fù)制代碼 public static SqlXml TransformXml (SqlXml XmlData, string xslPath) {// Load XSL transformationXslCompiledTransform xform = new XslCompiledTransform();XPathDocument xslDoc = new XPathDocument (xslPath);xform.Load(xslDoc);// Load XML data;XPathDocument xDoc = new XPathDocument (XmlData.CreateReader());// Return the transformed valueMemoryStream xsltResult = new MemoryStream();xform.Transform(xDoc, null, xsltResult);SqlXml retSqlXml = new SqlXml(xsltResult);return (retSqlXml);}
在注冊(cè)了程序集并創(chuàng)建了與 TransformXml() 對(duì)應(yīng)的用戶定義 Transact-SQL 函數(shù) SqlXslTransform() 之后,就可以從 Transact-SQL 中調(diào)用該函數(shù),如下面的查詢所示:
復(fù)制代碼 SELECT SqlXslTransform (xCol, 'C:MyFilexsltransform.xsl')FROM;TWHERE; xCol.exist('/book/title/text()[contains(.,'custom')]') =1
查詢結(jié)果包含轉(zhuǎn)換的 XML 的行集。
SQLCLR 擴(kuò)展了這樣一些功能:將 XML 數(shù)據(jù)分解到多個(gè)表或?qū)傩蕴嵘约巴ㄟ^使用 System.Xml 命名空間中的托管類查詢 XML 數(shù)據(jù)。有關(guān)詳細(xì)信息,請(qǐng)參閱 SQL Server 聯(lián)機(jī)叢書和 .Net Framework SDK 文檔。
跨域查詢當(dāng)您的數(shù)據(jù)同時(shí)保存在關(guān)系和 xml 數(shù)據(jù)類型列中時(shí),您可能希望編寫將關(guān)系和 XML 數(shù)據(jù)處理結(jié)合起來的查詢。例如,您可以通過使用 FOR XML 將關(guān)系列和 XML 列中的數(shù)據(jù)轉(zhuǎn)換為 xml 數(shù)據(jù)類型實(shí)例,并使用 XQuery 對(duì)其進(jìn)行查詢。相反,您可以從 XML 值生成行集,并使用 Transact-SQL 對(duì)其進(jìn)行查詢。
一種編寫跨域查詢的更方便且有效的方法是在 XQuery 或 XML DML 表達(dá)式中使用 SQL 變量或列的值:
您可以在 XQuery 或 XML DML 表達(dá)式中,通過使用 sql:variable() 來使用 SQL 變量的值。
您可以在 XQuery 或 XML DML 表達(dá)式中,通過使用 sql:column() 來使用關(guān)系列中的值。
通過這兩種方法,應(yīng)用程序可以對(duì)查詢進(jìn)行參數(shù)化,如以下示例所示。但在 sql:variable() 和 sql:column() 中不允許使用 XML 和用戶定義類型。
示例:使用 sql:variable() 的跨域查詢下面的查詢是“示例:對(duì)基于 xml 數(shù)據(jù)類型方法的計(jì)算列的查詢”中所示查詢的修改版本。在下面的版本中,使用 SQL 變量 @isbn 傳入了此特定 ISBN。通過將常量替換為 sql:variable(),可以使用查詢來搜索任何 ISBN,而不僅是 ISBN 為 0-7356-1588-2 的書。
復(fù)制代碼 DECLARE @isbn varchar(20)SET;;@isbn = '0-7356-1588-2'SELECT; xColFROM;TWHERExCol.exist ('/book/@ISBN[. = sql:variable('@isbn')]') = 1
可以用相似的方式使用 sql:column(),它提供了其他好處。可以使用列的索引來提高效率,這由基于開銷的查詢優(yōu)化器決定。另外,計(jì)算列可以存儲(chǔ)提升的屬性。
用于本機(jī) XML 支持的目錄視圖目錄視圖用于提供有關(guān) XML 用法的元數(shù)據(jù)信息。以下部分中討論了其中某些視圖。
XML 索引XML 索引項(xiàng)位于目錄視圖 sys.indexes 中,索引“type”為 3。名稱列包含 XML 索引的名稱。
另外,XML 索引還記錄在目錄視圖 sys.xml_indexes 中。此視圖包含 sys.indexes 的所有列和對(duì) XML 索引有用的某些特定列。secondary_type 列中的值 NULL 表示主 XML 索引;值“P”、“R”和“V”分別表示 PATH、PROPERTY 和 VALUE 輔助 XML 索引。
可以在表值函數(shù) sys.dm_db_index_physical_stats 中找到 XML 索引的空間使用情況。它提供了所有索引類型的相關(guān)信息,例如,占用的磁盤頁數(shù)、平均行大小(字節(jié))和記錄數(shù)。其中也包括 XML 索引。對(duì)于每個(gè)數(shù)據(jù)庫分區(qū),都提供此信息。XML 索引使用基表的相同分區(qū)方案和分區(qū)函數(shù)。
檢索 XML 架構(gòu)集合XML 架構(gòu)集合在目錄視圖 sys.xml_schema_collections 中枚舉出來。XML 架構(gòu)集合“sys”由系統(tǒng)定義。它包含無需顯式加載即可在所有用戶定義的 XML 架構(gòu)集合中使用的預(yù)定義命名空間。此列表包含 xml、xs、xsi、fn 和 xdt 的命名空間。另外兩個(gè)目錄視圖是 sys.xml_schema_namespaces(它枚舉每個(gè) XML 架構(gòu)集合中的所有命名空間)和 sys.xml_components(它枚舉每個(gè) XML 架構(gòu)中的所有 XML 架構(gòu)組件)。
內(nèi)置函數(shù) XML_SCHEMA_NAMESPACE(schemaName、XmlSchemacollectionName、namespace-uri)生成 xml 數(shù)據(jù)類型實(shí)例。此實(shí)例包含在 XML 架構(gòu)集合中所包含架構(gòu)(預(yù)定義的 XML 架構(gòu)除外)的 XML 架構(gòu)片段。
可以按下列方式枚舉 XML 架構(gòu)集合的內(nèi)容:
編寫對(duì) XML 架構(gòu)集合的相應(yīng)目錄視圖的 Transact-SQL 查詢。
使用內(nèi)置函數(shù) XML_SCHEMA_NAMESPACE()。您可以對(duì)此函數(shù)的輸出應(yīng)用 xml 數(shù)據(jù)類型方法。但不能修改基礎(chǔ) XML 架構(gòu)。
這些在下列示例中進(jìn)行了說明。
示例:枚舉 XML 架構(gòu)集合中的 XML 命名空間對(duì) XML 架構(gòu)集合“myCollection”使用下面的查詢:
復(fù)制代碼 SELECT XSN.nameFROM;sys.xml_schema_collections XSC JOIN sys.xml_schema_namespaces XSN;ON (XSC.xml_collection_id = XSN.xml_collection_id)WHERE;XSC.name = 'myCollection'
示例:枚舉 XML 架構(gòu)集合的內(nèi)容以下語句枚舉關(guān)系架構(gòu) dbo 中的 XML 架構(gòu)集合“myCollection”的內(nèi)容。
復(fù)制代碼 SELECT XML_SCHEMA_NAMESPACE (N'dbo', N'myCollection')
通過將目標(biāo)命名空間指定為 XML_SCHEMA_NAMESPACE() 的第三個(gè)參數(shù),可以按 xml 數(shù)據(jù)類型實(shí)例的形式獲得集合中的單個(gè) XML 架構(gòu)。如下面的示例所示。
示例:從 XML 架構(gòu)集合輸出指定的架構(gòu)以下語句從關(guān)系架構(gòu) dbo 中的 XML 架構(gòu)集合“myCollection”輸出目標(biāo)命名空間為“http://www.microsoft.com/books”的 XML 架構(gòu)。
復(fù)制代碼 SELECT XML_SCHEMA_NAMESPACE (N'dbo', N'myCollection', N'http://www.microsoft.com/books')
查詢 XML 架構(gòu)可以按下列方式查詢加載到 XML 架構(gòu)集合的 XML 架構(gòu):
編寫對(duì) XML 架構(gòu)命名空間的目錄視圖的 Transact-SQL 查詢。
創(chuàng)建包含 xml 數(shù)據(jù)類型列的表以存儲(chǔ) XML 架構(gòu),并將這些架構(gòu)加載到 XML 類型系統(tǒng)中。可以通過使用 xml 數(shù)據(jù)類型方法查詢 XML 列。另外,還可以對(duì)此列生成 XML 索引。但是,使用此方法時(shí),應(yīng)用程序必須保持 XML 列中存儲(chǔ)的 XML 架構(gòu)和 XML 類型系統(tǒng)之間的一致性。例如,如果從 XML 類型系統(tǒng)中刪除 XML 架構(gòu)命名空間,還必須從表中刪除它以保持一致性。
