一、XML 在 SQL Server 演進脈絡
從 SQL Server 2000 開始,Microsoft 逐步建構 XML 與關係數據的互操作體系。SQL Server 2005 達到里程碑:原生 XML 資料型別正式成為一等公民,配合 System.Xml 2.0、SQLXML 4.0,形成三大處理路徑。理解三者定位與適用場景,是構建高效 XML 應用的前提。
二、三大 XML 處理選項架構對比
| 維度 | System.Xml (ADO.NET 2.0) | SQLXML 4.0 (中介層) | 原生 XML 型別 (引擎內) |
| 核心定位 | 客戶端 XML DOM/Reader/Writer、XPath/XSLT/XQuery | 關係⇄XML 映射、範本查詢、HTTP/SOAP 端點 | 伺服器端儲存、索引、XQuery/DML、型別驗證 |
| 資料流向 | 應用層 ↔ 關係資料 (透過 DataSet/SqlXml) | 應用層 ↔ 關係資料 (透過映射結構描述) | 資料庫內部:XML 列、變數、參數、回傳值 |
| 查詢語言 | XPath 1.0 / XQuery (System.Xml.XPath) | XPath 1.0 子集 (對映射視圖) | XQuery 1.0 (W3C 標準)、XML DML (insert/delete/replace) |
| 結構驗證 | XmlSchemaSet (XSD) | 帶註釋 XSD (映射用) | XML 結構描述集合 (伺服器端強型別) |
| 索引/效能 | 無 (記憶體內) | 無 (依賴底層表索引) | 主要/次要/路徑/屬性索引,成本基礎優化 |
| 典型場景 | 文件處理、Web 服務序列化、小型 XML 片段 | 舊系統遷移、B2B 訊息轉換、HTTP 端點發布 | 半結構化資料、審計日誌、動態屬性、大型 XML 文件 |
三、SQL Server 2000 XML 回顧:奠基功能
- FOR XML:`RAW | AUTO | EXPLICIT` 模式產生 XML 串流
- OPENXML:將 XML 文件切碎為資料列集 (需 `sp_xml_preparedocument`)
- XML 視圖 (XDR/XSD 映射):雙向關係⇄XML 映射,支援 XPath 子集查詢
- HTTP 端點 (ISAPI):`sqlisapi.dll` 暴露範本/查詢為 Web 服務
- SQLXML 托管類:`SqlXmlCommand`、`SqlXmlParameter` 等 .NET 封裝
四、.NET Framework 2.0 System.Xml 增強
- 效能大幅提升:`XmlReader`/`XmlWriter` 非同步、流式處理
- 新增 `XPathNavigator` 編輯能力、`XmlSchemaSet` 快取驗證
- `SqlXml` 型別:`SqlCommand.ExecuteXmlReader` 直接回傳 `XmlReader`
- `DataSet` 支援 `DataColumn` 型別為 `DbType.Xml`,可直接繫結 XML 列
五、SQLXML 4.0 關鍵特性
- 純中介層:不包含伺服器端 `FOR XML`/`OPENXML`,專注映射與轉換
- 帶註釋 XSD:`sql:relation`、`sql:field`、`sql:relationship` 定義映射規則
- 大量載入:`SQLXMLBulkLoad` 高效將 XML 流入資料表
- 更新圖:`UpdateGram` 描述資料變更,自動轉為 INSERT/UPDATE/DELETE
- Web 服務支援:SOAP 端點、WSDL 產生、WS-I 相容
六、原生 XML 型別:遊戲規則改變者
1. 宣告與約束
CREATE TABLE dbo.Documents (
DocID INT PRIMARY KEY,
Content XML(CONTENT MySchemaCollection) -- 綁定結構描述集合,強型別
);
2. 五大 XML 方法
| 方法 | 用途 | 回傳型別 |
query() | XQuery 查詢,回傳 XML 片段 | XML |
value() | 提取單一純量值,需指定 T-SQL 型別 | 任意純量型別 |
exist() | 判斷 XQuery 是否有結果,用於 WHERE 子句 | BIT |
nodes() | 將 XML 切碎為關係資料列集 (替代 OPENXML) | rowset |
modify() | XML DML:insert/delete/replace 節點 | void |
3. XML 索引策略
- 主要 XML 索引:針對所有節點建立持久化結構 (路徑、值、類型)
- 次要索引:PATH (路徑查詢優化)、VALUE (值查詢優化)、PROPERTY (屬性包優化)
- 索引維護成本隨 XML 大小與更新頻率線性增長,需權衡讀寫比例
七、選型決策樹
- 資料是否持久化在資料庫?
- 是 → 考慮原生 XML 型別 (需索引、驗證、伺服器端查詢/修改)
- 否 → 考慮 System.Xml 或 SQLXML
- 是否需要關係⇄XML 雙向映射且不想寫 T-SQL?
- 是 → SQLXML 映射結構描述 + 更新圖/大量載入
- 否 → System.Xml 手工映射或原生 XML 型別 + FOR XML
- 是否需透過 HTTP/SOAP 直接暴露資料庫功能?
- 是 → SQLXML HTTP 端點 (注意:2008+ 棄用,建議改 WCF/Web API)
- 否 → 應用層自行封裝
- XML 文件大小與結構複雜度?
- 大型 (>1MB)、深層巢狀、頻繁部分更新 → 原生 XML 型別 + 索引 + `modify()`
- 小型、扁平、整體替換 → `VARBINARY(MAX)`/`NVARCHAR(MAX)` + 應用層處理
八、最佳實踐摘要
- 優先使用 原生 XML 型別 儲存半結構化業務資料,配合結構描述集合強制驗證
- 避免在高頻 OLTP 表中存放大型 XML;若必須,拆分至獨立表並建立適當 XML 索引
- 使用
nodes() + `CROSS APPLY` 替代 `OPENXML`,無需記憶體配置文件控制碼
- FOR XML 新增
PATH 模式 (替代 EXPLICIT)、TYPE 指令回傳 XML 型別、巢狀 FOR XML
- SQLXML 僅作為舊系統遷移橋樑,新專案建議採用原生 XML 型別 + 應用層 System.Xml
下篇將以實戰案例示範:訂單系統中動態屬性的 XML 建模、XQuery 查詢優化、XML 索引效能基準測試、以及 System.Xml 客戶端與伺服器端的協同模式。