核心概念速覽
| 技術 | 角色 | 關鍵語法 |
| XML | 資料載體 | 元素、屬性、值 |
| XPath | 定位語言 | . 當前、.. 父、/ 子、// 後代、@attr 屬性、[條件] 過濾 |
| XQuery | 查詢語言 | exist()、query()、value()、nodes() |
範例資料
DECLARE @data XML;
SET @data = '
Everyday Italian
Giada De Laurentiis
2005
30.00
Harry Potter
J K. Rowling
2005
29.99
XQuery Kick Start
James McGovern
Per Bothner
Kurt Cagle
James Linn
Vaidyanathan Nagarajan
2003
49.99
Learning XML
Erik T. Ray
2003
39.95
';
XQuery 方法實戰
| 需求 | XQuery 語句 | 說明 |
| 完整文檔 | SELECT @data | 直接輸出 XML 實例 |
| 任意層級是否存在 price | SELECT @data.exist('//price') | 返回 bit (1/0) |
| 所有 book 節點 | SELECT @data.query('//book') | 返回 XML 片段 |
| 含 lang 屬性的節點 | SELECT @data.query('//*[@lang]') | 屬性定位 |
| 第一個 book | SELECT @data.query('//book[1]') | 位置謂詞 |
| 前兩個 book | SELECT @data.query('//book[position() <= 2]') | 位置函數 |
| 最後一個 book | SELECT @data.query('//book[last()]') | last() 函數 |
| price > 35 的 book | SELECT @data.query('//book[price > 35]') | 數值比較 |
| category="WEB" 的 book | SELECT @data.query('//book[@category="WEB"]') | 屬性等值 |
| title lang="en" 的 book | SELECT @data.query('//book/title[@lang="en"]') | 路徑+屬性 |
| lang="en" OR price>35 | SELECT @data.query('//book[./title[@lang="en"] or price > 35]') | 邏輯或 |
| 符合條件第一本書的 title | SELECT @data.query('//book[./title[@lang="en"] and price > 35]').value('(book/title)[1]', 'varchar(max)') | query+value 組合 |
| 等價純 value 寫法 | SELECT @data.value('(//book[./title[@lang="en"] and price > 35]/title)[1]', 'varchar(max)') | 單一標量提取 |
| 第一本書 title 的 lang 屬性 | SELECT @data.value('((//book[@category="WEB" and price > 35]/title)[1]/@lang)[1]', 'varchar(max)') | 屬性提取 |
nodes() 方法:將 XML 拆解為關係行集
-- 15. 獲取第一本書的 title(以 bookstore 為上下文)
SELECT Tab.Col.value('(book/title)[1]', 'varchar(max)') AS title
FROM @data.nodes('bookstore') AS Tab(Col);
-- 16. 每本書的第一個 author
SELECT Tab.Col.value('author[1]', 'varchar(max)') AS author
FROM @data.nodes('//book') AS Tab(Col);
-- 17. 所有書完整信息扁平化
SELECT
T.C.value('title[1]', 'varchar(max)') AS title,
T.C.value('year[1]', 'int') AS year,
T.C.value('price[1]', 'float') AS price,
T.C.value('author[1]', 'varchar(max)') AS author1,
T.C.value('author[2]', 'varchar(max)') AS author2,
T.C.value('author[3]', 'varchar(max)') AS author3,
T.C.value('author[4]', 'varchar(max)') AS author4
FROM @data.nodes('//book') AS T(C);
-- 18. 非日文且價格>35 的書
SELECT ...
FROM @data.nodes('//book[./title[@lang!="jp"] and price > 35]') AS T(C);
最佳實踐建議
- 型別宣告:
value() 必須指定目標 SQL 型別,避免隱性轉換錯誤
- 單例要求:
value() 的 XPath 必須保證單一結果,否則報錯
- 效能考量:大型 XML 建立 XML 索引(主/次/屬性/路徑)大幅加速查詢
- 命名空間:生產環境 XML 通常含命名空間,需
WITH XMLNAMESPACES 宣告