`OPENXML` 是 SQL Server 2000+ 提供的將 XML 文檔轉為關係行集的核心函數,配合 `sp_xml_preparedocument`/`sp_xml_removedocument` 管理內存 DOM 樹。雖然 SQL 2005+ 引入原生 `xml` 類型與 XQuery(`.nodes()`/`.value()`),但 OPENXML 在舊版本兼容、大文檔流式處理、非標準 XML 結構適配場景仍具備不可替代價值。
OPENXML (
@idoc INT, -- sp_xml_preparedocument 返回的文檔句柄
@rowpattern NVARCHAR, -- XPath 模式,定位行節點(如 '/Person/row')
@flags BYTE = 0 -- 解析模式標誌位(核心參數)
)
[ WITH ( SchemaDeclaration | TableName ) ] -- 輸出列映射
官方文檔僅列舉 0/1/2/8,實際引擎按**二進制最低兩位**判斷:
| 二進制末兩位 | 十進制示例 | 語義 | 適用場景 |
|---|---|---|---|
| 00 / 01 | 0, 1, 4, 5, 8, 9... | 屬性中心:優先映射屬性,元素次之 | XML 以屬性為主(如 ` |
| 10 | 2, 6, 10, 14... | 元素中心:優先映射子元素,屬性次之 | XML 以元素為主(如 ` |
| 11 | 3, 7, 11, 15... | 混合模式:屬性與元素並行映射 | 屬性+元素共存(如 ` |
第 4 位(值 8):`XML_NO_COPY`,允許 OPENXML 直接引用內存 DOM 而非複製,大文檔(>10MB)顯著降低內存壓力,**但文檔句柄有效期內不可修改原 XML 變量**。
DECLARE @docHandle INT; DECLARE @xml XML = ''; EXEC sp_xml_preparedocument @docHandle OUTPUT, @xml; SELECT FirstName, MiddleName, LastName FROM OPENXML(@docHandle, '/Person/row', 1) -- 旗標 1 = 屬性中心 WITH (FirstName NVARCHAR(50), MiddleName NVARCHAR(50), LastName NVARCHAR(50)); EXEC sp_xml_removedocument @docHandle;
結果:
FirstName MiddleName LastName Gustavo NULL Achong Catherine R. Abel
DECLARE @xml XML = ''; -- 旗標 3 = 混合模式(屬性 Category + 元素 Name/Vendor) SELECT Category, Name, Vendor FROM OPENXML(@docHandle, '/Products/Product', 3) WITH (Category NVARCHAR(50), Name NVARCHAR(50), Vendor NVARCHAR(50)); Windows 2008 Vendor1
EXEC sp_xml_preparedocument @hDoc OUTPUT, @xml; -- ... OPENXML 查詢 ... EXEC sp_xml_removedocument @hDoc; -- 釋放內存 DOM 樹,防洩漏
| 維度 | OPENXML | XML 類型 (.nodes) |
|---|---|---|
| SQL 版本 | 2000+ | 2005+ |
| 解析模式 | DOM 全量載入內存 | 流式/迭代解析 |
| 大文檔 (>50MB) | 高內存風險,需 XML_NO_COPY | 原生支持,內存穩定 |
| XPath/XQuery 支持 | 有限 XPath 子集 | 完整 XQuery 1.0 |
| Schema 驗證 | 無 | 支持 XSD 集合驗證 |
| 性能(小文檔) | 略快(編譯開銷小) | 略慢(編譯優化) |
| 並發擴展性 | 受限於內存 | 優秀 |
OPENXML 是 XML 落地關係表的「經典橋樑」,掌握 `flags` 位掩碼語義、內存管理鐵律、映射規則,能駕馭複雜 XML 轉換場景。但在現代架構下,**原生 `xml` 類型配合 XQuery 是首選方向**,OPENXML 定位為兼容層與特殊場景補丁。將兩者能力邊界劃清,是數據集成工程師的必修課。