SQL Server 2005 引入原生 XML 資料類型,提供豐富的方法進行查詢、擷取、驗證與修改。本文記錄核心方法用法與實戰範例。
| 方法 | 用途 | 回傳類型 |
|---|---|---|
query() | XPath/XQuery 查詢,回傳 XML 片段 | XML |
value() | 擷取單一純量值,需指定轉換類型 | SQL 類型 |
exist() | 檢查 XPath 是否存在結果 | BIT (1/0) |
modify() | XML DML 更新(insert/delete/replace) | 無 |
nodes() | 將 XML 節點拆解為關聯式資料列集 | ROWSET |
CREATE TABLE VisioXML (ID INT, Doc XML)
GO
-- 從檔案載入 XML(需檔案位於伺服器端)
INSERT INTO VisioXML (ID, Doc)
SELECT 4, * FROM OPENROWSET(BULK 'e:\xxx.xml', SINGLE_BLOB) AS x
範例 XML 結構:
<ROOT>
<ROW><ID>1</ID><NAME SEX="MALE">WBQ</NAME></ROW>
<ROW><ID>2</ID><NAME SEX="FEMALE">CZH</NAME></ROW>
</ROOT>
SELECT
Doc.value('(/ROOT/ROW[1]/ID/text())[1]', 'int') AS RootRowID1,
Doc.value('(/ROOT/ROW[2]/ID/text())[1]', 'int') AS RootRowID2,
Doc.value('(/ROOT/ROW[1]/NAME/text())[1]', 'varchar(20)') AS RootRowNAME1,
Doc.value('(/ROOT/ROW[1]/NAME/@SEX)[1]', 'varchar(20)') AS RootRowNAME1SEX,
Doc.query('/ROOT') AS Root,
Doc.query('/ROOT/ROW[1]') AS RootRow1,
Doc.query('/ROOT/ROW[2]') AS RootRow2
FROM VisioXML WHERE ID = 4
關鍵點:value() 需加 [1] 指定單一節點,並強制轉型;query() 保留 XML 結構。
SELECT
Doc.exist('/ROOT/ROW[1]/NAME[(@SEX cast as xs:string?) = xs:string("MALE")]') AS Row1EQStringMale,
Doc.exist('/ROOT/ROW[1]/NAME[(@SEX cast as xs:string?) = "MALE"]') AS Row1EQMale,
Doc.exist('/ROOT/ROW[1]/ID[(text()[1] cast as xs:float?) = xs:float(1)]') AS Row1EQfloat1,
Doc.exist('/ROOT/ROW[2]/ID[(text()[1] cast as xs:float?) = 2]') AS Row1EQ1
FROM VisioXML WHERE ID = 4
SELECT ID, Doc
FROM VisioXML
WHERE ID = 4
AND Doc.exist('/ROOT/ROW[1]/NAME[@SEX]') = 1 -- 存在 SEX 屬性
-- AND Doc.exist('/ROOT/ROW[1]/NAME[not(@SEX)]') = 1 -- 不存在 SEX 屬性
-- 將每個 ROW 節點拆為一列
SELECT
T.C.value('(ID/text())[1]', 'int') AS ID,
T.C.value('(NAME/text())[1]', 'varchar(20)') AS Name,
T.C.value('(NAME/@SEX)[1]', 'varchar(10)') AS Sex
FROM VisioXML
CROSS APPLY Doc.nodes('/ROOT/ROW') AS T(C)
WHERE ID = 4
value() 而非 query() 擷取純量值,避免 XML 序列化開銷。JSON 功能,若資料結構簡單可考慮 JSON 替代。