本文探討 SQL Server 2005 中內建的 XML 支援。描述了這種支援如何與 .NET 架構 V2.0 和機器碼(例如 OLEDB 和 SQLXML)均支援的用戶端編程相整合。
一、簡介
可延伸標記語言 (XML) (XML) 作為一種與平台無關的資料表示形式已被廣泛採用。它對於在鬆散耦合且完全不同的系統,以及各種企業對企業 (B2B) (B2B) 應用和工作流程範疇內交換資訊是很有用的。資料交換已成為 XML 技術的主要驅動力之一。.
XML 在公司專屬應用程式程式中的使用正日益廣泛,它主要用於對半結構化和非結構化資料進行建模。文件管理就是這樣的一種應用程式。像電子郵件這樣的文檔是半結構化性質的。如果文檔以 XML 的形式儲存在資料庫伺服器中,就可以開發功能強大的應用程式來根據文檔內容檢索文檔、查詢部分內容(例如尋找標題包含單詞“背景”的部分),以及查詢文檔彙總。如果存在能夠產生和使用 XML 的應用程式,則這樣的方案就變得可行了。例如,Microsoft Office 2003 系統允許使用者以 XML 標記的形式產生 Word、Excel、Visio 和 Infopath 文檔。
為什麼使用關聯式資料庫來儲存 XML 資料?
• |
將 XML 資料存放區在關聯式資料庫中會給資料管理和查詢處理帶來好處。SQL Server 提供了強大的查詢和修改關係資料的能力,而且已經擴充到查詢和修改 XML 資料。這使得可以利用在過去的版本上所進行的投資,就如同基於成本的最佳化和資料存放區領域一樣。例如,關聯式資料庫中的索引技術已經廣為人知,而且已經擴充到用於索引 XML 資料,這樣就可以使用基於成本的決策來最佳化查詢。 |
• |
XML 資料可以與現有的關係資料和 SQL 應用程式進行互操作,這樣就可以在需要進行資料建模而又不破壞現有的應用程式的系統中引入 XML。資料庫伺服器還提供了管理功能來管理 XML 資料(例如備份、恢複和複製)。 |
• |
這些功能促進了對 SQL Server 2005 中的原生 XML 支援的需求,從而解決了不斷增加的 XML 使用的問題。SQL Server 2005 中的 XML 支援將給公司專屬應用程式程式開發帶來好處。 |
• |
下面幾部分將概述 SQL Server 2000 和 2005 中的 XML 支援,描述一些推動 XML 使用的方案,並且詳細討論區伺服器端和用戶端的 XML 功能集。 |
SQL Server 2000 中的 XML 支援
這一部分簡要概述了 SQL Server 2000 中的 XML 支援,以及隨後發布的 SQLXML 用戶端編程平台 Web 版,它提供了豐富的支援來將關係資料對應到 XML 資料或將 XML 資料對應到關係資料。
伺服器端支援
在伺服器上,XML 資料可以從表產生,並通過在 SELECT 語句中使用 FOR XML 子句來查詢結果。這對於資料交換和 Web 服務應用程式是很理想的。FOR XML 的逆函數是一個名為 OpenXML 的關係行集合產生器函數;它通過求 XPath 1.0 運算式的值來從 XML 資料提取值,並將其放到行集合的列中。應用程式使用 OpenXML 來“切碎”傳入 XML 資料,並將其存放到表中,或者用於通過 T-SQL 語言進行的查詢。
用戶端支援
SQL Server 2000 對用戶端編程的支援稱為 SQLXML。這項技術的核心是 XML 視圖,它是 XML 結構描述和關係表之間的雙向映射。SQL Server 2000 只支援 XDR 架構的映射,儘管在後續的 Web 版中增加了對 XSD 的支援。XML 視圖允許使用 XPath 1.0 的一個子集來進行查詢,其中,可以使用映射將路徑運算式轉換成底層表中的 SQL 查詢,並且將查詢結果打包成 XML 結果。
SQLXML 還支援您建立 XML 模板,這使得您可以建立帶有動態部分的 XML 文檔。在 XML 文檔中,您可以嵌入 FOR XML 查詢和/或映射查詢之上的 XPath 1.0 運算式。在執行 XML 模板時,可以用查詢的結果來替換查詢塊。通過這種方式,您可以建立帶有某些靜態內容和某些資料驅動的動態內容的 XML 文檔。
在SQL Server 2000 中,有兩種訪問 SQLXML 功能的主要方法:
• |
SQLXMLOLEDB Provider。SQLXMLOLEDB Provider 是一個 OLE DB 提供者,它通過 ADO 公開 Microsoft SQLXML 功能。 |
• |
HTTP 訪問。SQL Server 2000 中的 SQLXML 功能也可以使用 SQLXML ISAPI 過濾器通過 HTTP 進行訪問。通過使用我們的組態工具,您可以建立網站來檢索傳入請求,從而通過 HTTP 執行 XML 模板、XML 視圖之上的 FOR XML 和 XPath 1.0 語句。 |
XML 支援的局限性
伺服器和用戶端編程平台為基於表格和 XML 資料之間的映射產生和使用 XML 資料提供了豐富的支援。這能夠相當好地處理結構化 XML 資料。在 SQLXML 中,查詢語言是 XPath 1.0 的一個子集,並且有一些局限性。例如,不支援 descendant-or-self 軸 (//)。因此,在開發某些解決方案時會存在一定的限制。例如,不儲存 XML 文檔順序,而這對於像文件管理這樣的應用程式來說是非常關鍵的。此外,還不支援遞迴的 XML 結構描述。儘管存在這樣一些局限性,但是用戶端 SQLXML 和伺服器 XML 功能還是在應用程式開發中得到了廣泛的使用。SQL Server 2005 解決了許多這樣的限制,擴充了關係 XML 交換功能,並且還提供了原生 XML 支援。
SQL Server 2005 中的 XML 支援概述
這一部分簡要概述了 SQL Server 2005 中增加的新的 XML 支援,它是通過.NET 架構 V2.0 中的支援和本機用戶端資料訪問(如 OLE DB)進行補充的。
XML 資料類型
XML 資料模型具有一些特性,這些特性使得映射到關係資料模型非常困難,如果不是完全不可能的話。XML 資料具有可以遞迴的階層;關聯式資料庫提供對層次資料(建模為外鍵關係)的弱支援。文檔順序是 XML 執行個體的固有屬性,並且必須儲存在查詢結果中。這與關係資料形成了對比,關係資料是無序的,必須通過附加的排序列來強制進行排序。在查詢時重新組合結果是很費力的,因為實際的 XML 結構描述將 XML 資料分解到大量的表中。
SQL Server 2005 引入了一種稱為 XML 的本機資料類型。使用者可以建立這樣的表,它在關係列之外還有一個或多個 XML 類型的列;此外,還允許帶有變數和參數。為了更好地支援 XML 模型特徵(例如文檔順序和遞迴結構),XML 值以內部格式儲存為大型二進位對象 (BLOB)。
SQL Server 2005 提供了 XML 結構描述集合,可以將其作為一種方法來以中繼資料的形式管理 W3C XML 結構描述。XML 資料類型可以與 XML 結構描述集合相關聯,以便對 XML 執行個體強加架構限制。當 XML 資料與 XML 結構描述集合相關聯時,它稱為類型化的 XML;否則,就稱為非類型化的 XML。在一個架構中可以同時容納類型化的 XML 和非類型化的 XML,保留 XML 資料模型,並且強制採用 XML 語義進行查詢處理。底層關係基礎結構被廣泛用於這一目的。它支援關係資料和 XML 資料之間的互操作,這為更廣泛地採用 XML 功能開闢了道路。
XML 資料類型查詢和資料修改
可以使用 T-SQL SELECT 語句來檢索 XML 執行個體。在 XML 資料類型中提供了五種內建的方法來查詢和修改 XML 執行個體。
XML 資料類型的方法接受 XQuery,它是一種新出現的 W3C 標準語言(目前處於 Last Call(最後請求)狀態),並且包括導航語言 XPath 2.0。也可以使用一種語言來修改 XML 資料,比如添加或刪除子樹和更新標量值。與一大組函數一起,嵌入式的 XQuery 和資料修改語言為處理 XML 資料提供了豐富的支援。
XQuery 類型系統與 W3C XML 結構描述類型是一致的。大多數 SQL 類型與 XQuery 類型系統是相容的(例如,小數)。少數類型(例如,xs:duration)是以內部格式儲存的,並且可以通過適當的解釋來與 XQuery 類型系統相容。
編譯階段檢查 XQuery 運算式和資料修改語句的靜態類型的正確性,並且在類型化 XML 的情況下使用 XML 結構描述來進行型別推斷。如果運算式由於型別安全衝突而在運行時失敗,則會產生靜態類型錯誤。
XML 索引
查詢執行在運行時處理每個 XML 執行個體;如果 XML 值比較大或需要在表的許多行中對查詢進行求值,則查詢執行就會變得非常費時。因此提供了一種索引 XML 列的機制來加速查詢。
B+ 型樹狀結構廣泛用於建立關係資料的索引。XML 列的主 XML 索引在該列中 XML 執行個體的所有標記、值和路徑上都建立一個 B+ 型樹狀結構索引。通過這種方式,可以有效地對 XML 資料中的查詢進行求值,並且在保留文檔順序和文檔結構的同時從 B+ 型樹狀結構重新組合 XML 結果。
可以在 XML 列中建立次 XML 索引來加速不同類別的常見查詢:PATH 索引(用於基於路徑的查詢)、PROPERTY 索引(用於屬性包的情況)和 VALUE 索引(用於基於值的查詢)。
XML 結構描述處理
XML 列、變數和參數可以根據 XML 結構描述的集合(它可能與另一個集合相關(例如,通過使用 )或不相關)有選擇地進行類型化。每個類型化的 XML 執行個體都從它遵循的 XML 結構描述集合指定目標命名空間。資料庫引擎在資料分配和修改時根據 XML 結構描述來驗證執行個體的有效性。
XML 結構描述資訊用於儲存和查詢最佳化。類型化的 XML 執行個體在內部的二進位表示中包含類型化的值,這與 XML 索引中的一樣。通過這種方式,可以有效地處理類型化 XML 資料。
關係資料和 XML 資料的整合
使用者可以在同一個資料庫中儲存關係資料和 XML 資料。簡而言之,資料庫引擎除了知道如何遵循關係資料模型之外,還知道如何遵循 XML 資料模型。在升級到 SQL Server 2005 之後,關係資料和 SQL 應用程式仍然能夠正常工作。在伺服器上,可以將駐留在檔案和文本或映像列中的 XML 資料移到 XML 資料類型的列中。通過使用 XML 資料類型的方法,可以建立 XML 列的索引,並對其進行查詢和修改。
資料庫利用現有的關係基礎結構和引擎組件(例如儲存引擎和查詢處理器)來進行 XML 處理。例如,XML 索引可以建立 B+ 型樹狀結構,而且可以在 Showplan 輸出中查看查詢計劃。通過整合到關係架構中,資料管理功能(如備份/恢複和複製)可用於 XML 資料。同樣地,新的資料管理功能(如資料庫鏡像和快照隔離)可以處理 XML 資料類型,以提供無縫的使用者體驗。
結構化資料應該儲存在表和關係列中。當應用程式需要執行細粒度查詢和資料修改時,對於使用 XML 的半結構化資料和標記資料,XML 資料類型是比較合適的選擇。
FOR XML 和 OpenXML 增強
現有的 FOR XML 功能已經在幾個方面得到了增強。它能夠處理 XML 資料類型的執行個體和其他新的 SQL 類型,例如 [n]varchar(max)。
新的 TYPE 指令產生的 XML 資料類型執行個體可以分配給 XML 列、變數或參數,也可以使用 XML 資料類型的方法進行查詢。這允許嵌套 SELECT ...FOR XML TYPE 語句。
PATH 模式允許使用者指定出現列值的 XML 樹中的路徑,並且與上述嵌套一起使用時比 FOR XML EXPLICIT 更易於編寫。
XSINIL 指令與 ELEMENTS 一起使用,可以將 NULL 映射到帶有屬性 xsi:nil="true" 的元素。另外,新的 ROOT 指令還允許在所有的 FOR XML 模式下指定根節點。新的 XMLSCHEMA 指令產生 XSD 內聯架構。
OpenXML 的功能增強包括在 sp_preparedocument 中接受 XML 資料類型以及在行集中產生 XML 和新的 SQL 類型的列。
對 XML 資料類型的用戶端訪問
用戶端可以通過幾種方式訪問伺服器中的 XML 資料。使用 ODBC 和 OLE DB 的本機 SQL 用戶端訪問以 Unicode 字串的形式傳遞 XML 資料類型。OLE DB 還提供對流 Unicode 資料的 XML 資料類型的 ISequentialStream 訪問。
託管訪問通過 .NET 架構 V2.0 中的 ADO.NET 將 XML 資料作為一個名為 SqlXml 的新類進行傳遞。它支援一個名為 CreateReader() 的方法,該方法返回 XmlReader 執行個體來讀取返回的 XML。同樣地,資料集能夠將 XML 資料類型的執行個體載入到中介層的列,中介層可以作為 XML 文檔進行編輯,並且重新儲存到 SQL Server。這兩者都支援對伺服器發出 SQL 查詢,以檢索在中介層操作的 XML 列。
在 SQL Server 2005 中,可以使用直接對 HTTP 終結點進行的SOAP 訪問來查詢、檢索和修改 XML 資料。
本機和託管用戶端技術都提供了新的介面來檢索類型化 XML 列的 XML 結構描述集合。
帶有 XQuery 的用戶端 XML 支援
除了使用 ADO.NET 來檢索表並將結果存放到關係資料集中之外,您還可以使用 XQueryCommand 類將關係資料直接載入到中介層的 XML 文檔。該類提供了一個中介層 XQuery 處理器,它能夠將 T-SQL 陳述式作為 XQuery 語言的一部分嵌入。通過這種方式,您可以查詢本地 XML 檔案,也可以從 SQL Server 檢索資料(直接從表或者通過資料庫儲存程式),再將資料構造成 XML 格式,然後將其載入到中介層 XML 文檔。這大大簡化了 SQL Server 中的查詢,將查詢結果構造成特定的 XML 格式,並使其流向業務夥伴,而不需要將資料載入到資料集來執行資料轉換。
二、推動 XML 儲存方案
XML 資料變得越來越普遍.它可以表示客戶資料,帶有或不帶有描述資料的 XML 結構描述均可。XML 資料和 XML 結構描述需要在一起進行管理。實際應用程式的 XML 結構描述通常比較複雜,因而將這樣的 XML 結構描述映射到表和列是一項複雜的任務。當 XML 結構描述改變或新的架構加入系統時,長時間維護這樣的映射是一件很麻煩的事情。通常,XML 資料存放區在檔案系統或資料庫伺服器的文本列中。文本列有資料管理方面的好處(例如,複製和備份/恢複),但是不提供任何基於資料的 XML 結構的查詢支援。在具有原生 XML 支援的情況下,使用 XML 進行應用程式開發變得更快。
自訂屬性管理
一些應用程式(例如使用者介面軟體)允許使用者從一組固定的屬性中進行選擇。而其他應用程式則允許使用者定義他們自己感興趣的屬性。如果這樣的自訂屬性是以 XML 的格式儲存的,它們就可以很好地進行管理。應用程式可以支援純量屬性以外的屬性:
• |
可以支援對象中的多值屬性,例如,多個電話號碼。 |
• |
可以支援複雜屬性,例如,一個文檔的作者屬性可能是該作者的聯絡資訊。 |
可以將對象屬性儲存區在 XML 資料類型的列中並建立索引,從而提高查詢處理的效率。
資料交換和工作流程
XML 允許採用平台無關的方式在應用程式之間交換資料。可以使用 XML 標記將這樣的資料建模為訊息。代替不斷地分割和產生 XML 訊息,以 XML 的格式儲存訊息是明智的。這正是資料流所需要的。到達工作流程階段的 XML 訊息攜帶著當前的狀態。每個訊息都需要進行處理,處理的進展記錄在 XML 內容中(如狀態改變),然後將 XML 資料轉寄到工作流程處理的下一個階段。訊息可能是不同類型的,甚至可能是半結構化的,並且有不同的 XML 結構描述與它們相關聯,因此將它們映射到表並不總是一件輕而易舉事。
針對不同垂直領域(如金融資料和地理空間資料)的基於 XML 的標準正在形成。這些標準根據可以查詢和更新的執行個體資料來描述資料的結構。通常,實際資料採用的是二進位形式,而 XML 資料提供關於它們的中繼資料資訊。
舉一個簡單的例子,為了將一個輸入參數表傳送到儲存程式或函數,應用程式首先將資料轉換成 XML,然後將其作為一個 XML 資料類型參數進行傳遞。在預存程序或函數內,從 XML 參數重建行集。
文件管理
假設有一個話務中心,它採用 XML 文檔來維護患者記錄和談話。當患者發起呼叫時,話務中心希望恢複前面的談話以設定撥入電話的情景。這可以通過查詢 XML 標記實現,從而給應用程式帶來好處。此外,還可以方便地檢索以前談話的細節並記錄當前的談話。
像電子郵件之類的文檔本質上是半結構化的。帶有 XML 標記的文檔正變得越來越容易建立,例如,使用 Office 2003。可以將這些 XML 文檔儲存在 XML 列中,並建立索引,進行查詢和更新。因此,通過利用原生 XML 支援,開發人員可以做更多的事情。
三、SQL Server 2005 中的伺服器端 XML 處理
SQL Server 2005 支援包括提供一個資料庫,在這個資料庫中,您可以儲存關係資料和 XML 資料。
XML 資料類型
您可以使用普通的 CREATE TABLE 語句來建立帶有 XML 列的表。然後就可以採用一種特別的方式來建立 XML 的索引。
非類型化的 XML
SQL Server 2005 XML 資料類型實現了 ISO SQL-2003 標準 XML 資料類型。因此,它不僅可以儲存格式良好的 XML 1.0 文檔,而且可以儲存所謂的 XML 內容片段(帶有文本節點和任意數目的頂層元素)。在對資料進行格式良好性檢查時,並不要求將 XML 資料類型綁定到 XML 結構描述,但是格式不規範的資料將被拒絕。
當架構不是已知先驗的 並且因此而導致基於映射的解決方案不可能實現時,就可以使用非類型化的 XML。如果架構是已知的,但映射到關係資料模型非常複雜並且難於維護,或者存在多個架構而且這些架構是後來根據外部要求綁定到資料的,也可以使用非類型化的 XML。
例:表中非類型化的 XML 列
下面的語句建立一個名為“docs”的表,該錶帶有整型主鍵“pk”和非類型化的 XML 列“xCol”:
CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not null)
也可以建立一個包含多個 XML 列或關係列、帶主鍵或不帶主鍵的表。
類型化的 XML
如果 XML 結構描述集合中有描述 XML 資料的 XML 結構描述,就可以將 XML 結構描述集合與產生類型化 XML 的 XML 列相關聯。可以使用 XML 結構描述來驗證資料的有效性,在編譯查詢和資料修改語句時執行比非類型化的 XML 更精確的類型檢查,以及最佳化儲存和查詢處理。
類型化的 XML 列、參數和變數可以儲存 XML 文檔或內容,可以在聲明時將其指定為一個選項(分別為DOCUMENT 或 CONTENT,預設為 CONTENT)。此外,還必須提供 XML 結構描述集合。如果每個 XML 執行個體都正好有一個頂層元素,則指定 DOCUMENT;否則,使用 CONTENT。查詢編譯器在類型檢查中使用 DOCUMENT 標記來推理 singleton 頂層元素。
例:表中的類型化 XML 列
XML 列、變數和參數可以綁定到一個 XML 結構描述集合(請參閱本文後面的“XML 結構描述處理”一節以獲得更多的詳細資料和樣本)。假定 myCollection 代表這樣一個集合。下面的語句建立一個表 XmlCatalog,帶有使用 myCollection 進行類型化的 XML 列文檔。類型化的 XML 列還被指定為接受 XML 片段,而不只是 XML 文檔。
CREATE TABLE XmlCatalog (
ID INT PRIMARY KEY,
Document XML(CONTENT myCollection))
約束 XML 資料類型的列
• |
除了類型化一個 XML 列之外,還可以在類型化和非類型化的 XML 資料類型的列中使用關係(列或行)約束。大部分 SQL 約束同樣可應用於 XML 列,值得注意的唯一例外是主鍵和外鍵約束,因為 XML 資料類型的執行個體是不相容的。因此,可以指定 XML 列可為空白或不可為空白,提供預設值,並且在列中定義 CHECK 條件約束。例如,非類型化的 XML 列可以有 CHECK 條件約束來驗證儲存的 XML 執行個體是否符合 XML 結構描述。 |
在下列條件下使用約束:
• |
商務規則不能用 XML 結構描述表示。例如,花店的交付地址必須在其業務場所 50 英裡的範圍內,這可以編寫成 XML 列中的一個約束條件。該約束條件可以包括 XML 資料類型的方法。 |
• |
約束條件涉及表中其他的 XML 或 非 XML 列。這樣的一個例子就是,使 XML 執行個體中存在的 Customer (/Customer/@CustId) 的id 與整型 CustomerID 列中的值相匹配。 |
例:約束 XML 列
要確定<book>的<author>的<last-name> 不同於<author>的<first-name> ,可以指定下列 CHECK 條件約束:
CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not nullCONSTRAINT CK_name CHECK (xCol.exist('/book/author[first-name = last-name]') = 0))
文本編碼
SQL Server 2005 將 XML 資料存放區為 Unicode (UTF-16)。從伺服器檢索的XML 資料,其結果也是 UTF-16 編碼的。如果想要採用一種不同的編碼方式,就需要在檢索資料之後進行必要的轉換,轉換的方法有兩種,一種是通過強制類型轉換,另一種是在中介層執行轉換。例如,可以在伺服器上將 XML 資料強制轉換成 varchar 類型,在這種情況下,資料庫引擎會通過 varchar 類型的排序所確定的編碼方式來序列化 XML。
儲存 XML 資料
可以通過多種方式為 XML 列、參數或變數提供 XML 值。
• |
作為隱式轉換到 XML 資料類型的字元或二進位 SQL 類型。 |
• |
作為檔案的內容。 |
• |
作為 XML 發布機制 FOR XML 的輸出(帶有產生 XML 資料類型執行個體的 TYPE 指令) |
對提供的值進行格式良好性檢查,並且允許儲存 XML 文檔和 XML 片段。如果資料沒有通過格式良好性檢查,則拒絕它,並發出一個適當的錯誤訊息。
對於類型化的 XML,需要檢查提供的值是否符合登入到類型化 XML 列的 XML 結構描述集合的 XML 結構描述。如果該 XML 執行個體沒有通過這種有效性驗證,則拒絕它。此外,僅當 CONTENT 允許提供 XML 文檔和內容時,類型化的 XML 中的 DOCUMENT 標記才將所接受的值限制為 XML 文檔。
例:將資料插入非類型化的 XML 列
下列語句在表 docs 中新插入一行,其中在整型的 pk 列插入的值為 1,而在 XML 列插入的是 執行個體。 資料(作為字串提供)被隱式地轉換為 XML 資料類型,並且在插入的過程中進行格式良好性檢查。
INSERT INTO docs VALUES (1,
'<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>')
例:將來自檔案的資料插入非類型化的 XML 列
如下所示的 INSERT 語句使用 OPENROWSET 讀取檔案 C: empxmlfile.xml 的內容作為 BLOB。在表 docs 中新插入一行,值 10 作為主鍵,而 BLOB 作為 XML 列 xCol。格式良好性檢查出現在檔案內容分配到 XML 列時。
INSERT INTO docs
SELECT 10, xCol
FROM (SELECT * FROM OPENROWSET
(BULK 'C: empxmlfile.xml',
SINGLE_BLOB) AS xCol) AS R(xCol)
例:將資料插入類型化的 XML 列
類型化的 XML 列需要 XML 執行個體資料指定用於對其進行類型化的 XML 結構描述的目標命名空間(該命名空間可以為空白)。在下面的樣本中,這是通過命名空間聲明 xmlns=http://myDVD 來實現的。
INSERT XmlCatalog VALUES(2,
'<?xml version="1.0"?>
<dvdstore xmlns="http://myDVD">
<dvd genre="Comedy" releasedate="2003">
<title>My Big Fat Greek Wedding</title>
<price>19.99</price>
</dvd>
</dvdstore>')
例:儲存使用帶有 TYPE 指令的 FOR XML 產生的 XML 資料
通過 TYPE 指令增強 FOR XML 可以產生像 XML 資料類型執行個體這樣的結果。結果 XML 可以分配到 XML 列、變數或參數。在下面的語句中,使用 FOR XML TYPE 產生的 XML 執行個體被分配給 XML 資料類型的變數 @xVar。可以使用 XML 資料類型的方法來查詢變數。
DECLARE @xVar XML
SET @xVar = (SELECT * FROM docs FOR XML AUTO,TYPE)
儲存表示
XML 資料類型的執行個體儲存在內部的二進位表示中,該表示是可流化的,並且經過了最佳化,從而可以更有效地進行解析。標記映射到整型值,而映射的值儲存在內部表示中。這也產生了一些資料的壓縮。
對於非類型化的 XML,節點值儲存為 Unicode (UTF-16) 字串,因此需要進行運行時類型轉換才能執行操作。例如,為了求謂詞 /book/price > 9.99 的值,必須將該書的價格值轉換為小數。而對於類型化的 XML,值的編碼類別型為在 XML 結構描述中指定的類型。這使得資料的解析更加有效,並且還不必進行運行時轉換。
儲存的二進位形式被限制為每 XML 執行個體 2 GB,這可以適應大部分的 XML 資料。此外,XML 層次的深度還被限制為 128 層。
XML 資料的資訊集內容被保留。但是,它不可能是與文本 XML 一模一樣的副本,因為下列資訊沒有保留:無關緊要的空白、屬性的順序、命名空間首碼和 XML 聲明。
資料建模考慮事項
通常,關係資料類型和 XML 資料類型的列的組合比較適合資料建模。可以將 XML 資料中的一些值儲存在關係列中,而將其餘的值或全部的 XML 值儲存在 XML 列中。這可以產生更好的效能和鎖定特性。
對於 singleton 值(即單值屬性),XML 資料中的值可以提升為同一個表中的計算資料行。多值屬性需要單獨的屬性工作表,該表必須使用觸發器進行填充和維護。查詢需要直接針對屬性工作表進行編寫。
對於鎖定和更新特性,儲存在 XML 列中的 XML 資料的粒度是至關重要的。SQL Server 將相同的鎖定機制用於 XML 和非 XML 資料。如果粒度比較大,則在多使用者的情況下,為了更新而鎖定大的 XML 執行個體會引起輸送量的下降。而另一方面,嚴格的分解會失去對象的封裝性並增加重新組合的成本。
查詢和修改 XML 資料
查詢儲存在 XML 列中的 XML 執行個體需要解析列中的二進位 XML 資料。與解析文本形式的 XML 資料相比,解析二進位的 XML 要快得多。XML 索引避免了重新解析,這將在“建立 XML 資料的索引”一節中進行討論。
XML 資料類型中的方法
如果感興趣,可以檢索全部 XML 值,也可以檢索部分 XML 執行個體。這可以使用四個 XML 資料類型的方法來實現:query()、value()、exist() 和 nodes(),它們接受 XQuery 運算式作為參數。第五個方法 modify() 允許修改 XML 資料並接受 XML 資料修改語句作為輸入。
query() 方法用於提取 XML 執行個體的部分。XQuery 運算式求值為一個 XML 節點列表。以這些節點中的每一個為根的子樹按照文檔順序返回。結果類型為非類型化的 XML。
value() 方法從 XML 執行個體提取標量值。它返回 XQuery 運算式所求值的節點的值。該值被轉換為 value() 方法的第二個參數所指定的 T-SQL 類型。
exist() 方法用於對 XML 執行個體進行存在性檢查。如果 XQuery 運算式求值為非空節點列表,則返回 1;否則,返回 0。
nodes() 方法產生特定 XML 資料類型的執行個體,每個執行個體都將其上下文設定為 XQuery 運算式所求值的不同節點。特定的 XML 資料類型支援 query()、value()、 nodes() 和 exist() 方法,並且可以用於 count(*) 彙總和 NULL 檢查。所有其他的使用都會產生錯誤。
modify() 方法允許修改 XML 執行個體的某些部分,例如添加或刪除子樹,或者更新標量值(如將書的價格從 9.99 替換為 39.99)。
例:使用 query() 方法
考慮下面的表 docs 的 XML 列 xCol 中的查詢,它提取 元素下的任何位置的 id 為 123 的 元素。該查詢也從整型主鍵列檢索值。SELECT 列表中的 query() 方法會為產生 元素序列的表中的每一行進行求值, 元素及其子樹是按照文檔順序進行檢索的。對於每個 XML 執行個體,如果沒有 id 為 123 的 元素或者其下沒有 元素,則不會返回結果,也就是說,query() 方法的傳回值為 NULL。
SELECT pk, xCol.query('/doc[@id = 123]//section')
FROM docs
NULL 傳回值可以在外部 SELECT 語句中過濾掉。或者也可以使用 exist() 方法,如下一個樣本所示。
例:使用 exist() 方法
考慮下面的查詢,它在表 docs 的 XML 列 xCol 中包括 query() 和 exist() 方法。exist() 方法求路徑運算式 /doc[@id = 123] 的值,檢查是否存在頂層 元素,該元素具有一個稱為 id 的屬性,且其值為 123。對於每個這樣的行,SELECT 子句中的 query() 方法都會進行求值;在這個樣本中,query() 方法在 元素下的任何位置都產生一個 元素序列。從 exist() 方法返回 0 的任何行都會被忽略。
SELECT xCol.query('/doc[@id = 123]//section')
FROM docs
WHERE xCol.exist ('/doc[@id = 123]') = 1
例:使用 value() 方法
下面的查詢使用 value() 方法以 Unicode 字串的形式提取文檔第三部分的標題。結果的 SQL 類型的 nvarchar(max) 被指定為 value() 方法的第二個參數。XQuery 函數 data() 從 節點提取標量值。
SELECT xCol.value( 'data((/doc//section[@num = 3]/heading)[1])', 'nvarchar(max)') FROM docs
XQuery 語言
眾多的 XML 都來源於儲存在檔案系統、Web 服務或設定檔中的 Office 文檔。事實上,以 XML 格式或作為虛擬 XML 文檔產生的資料正在不斷地增加。為了處理這些數量越來越多的資料,一種強大的查詢語言 XQuery 應運而生。在 XQuery 語言規範(位於 http://www.w3.org/TR/xquery)中將選擇 XQuery 的理由描述為:
• |
一種巧妙地使用 XML 結構的查詢語言,可以跨各種資料表示查詢,而不管這些資料是實體儲存體在 XML 中,還是通過中介軟體被視為 XML。該規範描述了一種稱為 XQuery 的查詢語言,它旨在能廣泛應用於許多類型的 XML 資料來源。 |
• |
XQuery 旨在滿足 W3C XML 查詢工作群組 XML 查詢 1.0 要求和 XML 查詢用例中的用例所確定的要求。它是一種旨在使查詢簡潔易懂的語言。它還相當地靈活,可以查詢大範圍的 XML 資訊源,其中包括資料庫和文檔。 |
• |
XQuery 還可以概括為如下表述:XQuery 語言之於 XML 正如 SQL 語言之於關聯式資料庫。 |
內嵌於 T-SQL 的 Xquery 子集(位於 http://www.w3.org/TR/xquery/)是一種支援查詢 XML 資料類型的語言。這種語言正在由 Worldwide Web Consortium (W3C) 進行開發(目前處於最後請求狀態),所有主要的資料庫廠商(包括 Microsoft 在內)都參與其中。我們的實現與 2003 年 11 月發布的 XQuery 草案是一致的。
XQuery 將 XPath 2.0 作為導航語言套件括在內。SQL Server 2005 的 XQuery 實現提供了用於遍曆節點 (for)、節點檢查 (where)、傳回值 (return) 和排序 (order by) 的構造。它也提供了用於在查詢過程中重新進行資料構形的元素構造。
SQL Server 2005 還提供了用於 XML 資料類型的資料修改 (DML) 的語言構造(請參閱下面的“資料修改”一節以獲得更多資訊)。下面的樣本示範了如何將 XQuery 用於 XML 資料類型。
例:使用 XQuery 中豐富的語言構造
下面的查詢顯示了如何一起使用幾個 XQuery 語言構造。它從 id 為 123 的文檔返回地區號為 3 和更高的地區中的標題,並將其封裝在新標記 中。
SELECT pk, xCol.query('
for $s in /doc[@id = 123]//section
where $s/@num >= 3
return <topic>{data($s/heading)}</topic>')
FROM docs
“for”遍曆 id 為 123 的<doc> 元素下的所有<section> 元素,並且將每個這樣的<section> 元素繫結到變數 $s。“where”確保地區號(<section> 元素的 @num 屬性)為 3 或更高。該查詢按照文檔順序返回地區<heading> 中的值,並且將其封裝在一個稱為<topic> 的構造元素中。
查詢編譯和執行
SQL 陳述式是由 SQL 解析器解析的。當它遇到 XQuery 運算式時,它就會跳轉到 XQuery 編譯器,然後編譯 XQuery 運算式。這會產生一個查詢樹,並將其嫁接到整個查詢的查詢樹上。
整個查詢樹會進行查詢最佳化併產生物理查詢計劃,該計劃是根據基於成本的評估得出的。Showplan 輸出顯示了大部分關係運算子和一些新的運算子(例如,用於 XML 處理的 UDX)。
查詢執行與關係架構中的其餘部分一樣,都是面向元組的。在表 docs 的每一行上都求 WHERE 子句的值;這需要在運行時解析 XML BLOB 以求出 XML 資料類型方法的值。如果條件滿足,則鎖定行,然後在行中求 SELECT 子句的值。結果以 XML 資料類型的形式產生(用於 query() 方法),並且轉換成指定的目標類型(用於 value() 方法)。
而如果該行不滿足 WHERE 子句中的條件,它就會被忽略,執行轉到下一行。