XPath 資料類型 (SQLXML 4.0)
Microsoft SQL Server、XPath 和 XML 架構 (XSD) 具有非常不同的數據類型。 例如,XPath 沒有整數或日期數據類型,但 SQL Server 和 XSD 有許多。 XSD 會針對時間值使用奈秒有效位數,而 SQL Server 最多使用 1/300 秒的有效位數。 因此,不一定可以將一個數據類型對應到另一個數據類型。 如需將 SQL Server 數據類型對應至 XSD 資料類型的詳細資訊,請參閱 資料類型強制型別和 sql:資料類型批注 (SQLXML 4.0) 。
XPath 有三種數據類型: 字串、 數位和 布爾值。 數字數據類型一律為 IEEE 754 雙精確度浮點數。 SQL Serverfloat(53) 資料類型最接近 XPath 數位。 不過, float(53) 不完全是 IEEE 754。 例如,不會使用 NaN (Not-a-Number) 和無限大。 嘗試將非數值字串 轉換成數位 ,並嘗試除以零會導致錯誤。
XPath 轉換
當您使用 XPath 查詢時,例如 OrderDetail[@UnitPrice > "10.0"]
,隱含和明確的數據類型轉換可能會以微妙的方式變更查詢的意義。 因此,請務必瞭解 XPath 數據類型的實作方式。 您可以在 W3C 網站 http://www.w3.org/TR/1999/PR-xpath-19991008.html找到 XPath 語言規格、XML 路徑語言 (XPath) 1.0 版 W3C 建議建議 1999 年 10 月 8 日。
XPath 運算子分成四個類別:
布林運算子 (和, 或)
關係運算子 (<, , <>=, >=)
等號運算子 (=, !=)
算術運算子 (+, -, *, div, mod)
運算子的每個類別都會以不同的方式轉換其操作數。 如有必要,XPath 運算符會隱含地轉換其操作數。 算術運算子會將其操作 數轉換成 number,併產生數位值。 布爾運算子會將操作數 轉換成布爾值,併產生布爾值。 關係運算子和相等運算符會產生布爾值。 不過,根據操作數的原始數據類型,它們有不同的轉換規則,如下表所示。
運算元 | 關聯式運算子 | 等號比較運算子 |
---|---|---|
這兩個操作數都是節點集。 | 如果 和 只有一個集合中有一個節點,而第二個集合中的節點,則為 TRUE,因此其 字串 值的比較為 TRUE。 | 相同。 |
一個是節點集,另一個是 字串。 | 如果節點集中有節點,則為TRUE,如此一來,當轉換成數位時,其與轉換成數位的字串比較為TRUE。 | 如果節點集中有節點,則為TRUE,如此一來,當轉換成字元串時,與字串串的比較就會是 TRUE。 |
一個是節點集,另一個是 數位。 | 如果節點集中有節點,則為TRUE,如此一來,當轉換成 數位時,其與 數字 的比較為TRUE。 | 相同。 |
一個是節點集,另一個是 布爾值。 | 如果節點集中有節點,則為TRUE,如此一來,當轉換成布爾值,然後轉換成數位時,其與轉換成數位的布爾值比較為TRUE。 | 如果節點集中有節點,則為TRUE,因此當轉換成 布爾值時,與 布爾值的 比較為TRUE。 |
兩者都不是節點集。 | 將這兩個操作數轉換成 數位 ,然後比較。 | 將這兩個操作數轉換成一般類型,然後比較。 如果其中一個為布爾值,則轉換成布爾值,如果其中一個為 number,則為 number;否則,轉換為字串。 |
注意
因為 XPath 關係運算符一律會將其操作數 轉換成數位, 因此無法進行字串 比較。 若要包含日期比較,SQL Server 2000 會提供這個變化給 XPath 規格:當關係運算符比較字串與字串、節點集為字串,或字串值節點集設定為字元串值節點集時,就會執行字串串比較(而非數位比較)。
節點集轉換
節點集轉換不一定是直覺式的。 節點集會藉由只取得集合中第一個 節點的字串值,轉換為字串 。 節點集會藉由將節點集轉換成字串,然後將字串轉換為 number,以轉換為數位。 節點集會藉由測試其存在而轉換成 布爾值 。
注意
SQL Server 不會在節點集上執行位置選取:例如,XPath 查詢 Customer[3]
表示第三個客戶;SQL Server 不支援這種類型的位置選取。 因此,不會實作 XPath 規格中所述的 node-set-to-string 或 node-set-to-number 轉換。 無論 XPath 規格指定「第一個」語意,SQL Server 都會使用「任何」語意。 例如,根據 W3C XPath 規格,XPath 查詢Order[OrderDetail/@UnitPrice > 10.0]
會選取具有 UnitPrice 大於 10.0 之第一個 OrderDetail 的訂單。 在 SQL Server 中,此 XPath 查詢會選取任何 OrderDetail 且 UnitPrice 大於 10.0 的訂單。
轉換成布爾值會產生存在測試;因此,XPath 查詢Products[@Discontinued=true()]
相當於 SQL 運算式 「Products.Discontinued 不是 null」,而不是 SQL 表達式 「Products.Discontinued = 1」。。 若要讓查詢與后一個 SQL 運算式相等,請先將節點集轉換成非布爾 型別,例如 number。 例如: Products[number(@Discontinued) = true()]
。
因為如果節點集中的任何節點或其中一個節點都是 TRUE,則大部分運算子都會定義為 TRUE,所以如果節點集是空的,這些作業一律會評估為 FALSE。 因此,如果 A 是空的, A = B
則 和 A != B
都是 FALSE,且 not(A=B)
為 not(A!=B)
TRUE。
通常,如果資料庫中該數據行的值不是 Null,則對應至數據行的屬性或專案存在。 如果有任何子系存在,則對應至數據列的元素存在。
注意
以 is-constant 標註的專案一律存在。 因此,XPath 述詞無法在is-constant 元素上使用。
當節點集轉換成 字串 或 數位時,會在批註架構中檢查其 XDR 類型(如果有的話),並使用該類型來判斷所需的轉換。
將 XDR 數據類型對應至 XPath 資料類型
節點的 XPath 數據類型衍生自架構中的 XDR 數據類型,如下表所示(node EmployeeID 用於說明用途)。
XDR 資料類型 | 對等 XPath 數據類型 |
使用的 SQL Server 轉換 |
---|---|---|
Nonebin.base64bin.hex | N/A | NoneEmployeeID |
boolean | boolean | CONVERT(bit, EmployeeID) |
number, int, float,i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 | 數值 | CONVERT(float(53), EmployeeID) |
id、idref、idrefsentity、entities、enumerationnotation、nmtoken、nmtokens、chardate、Timedate、Time.tz、string、uri、uuid | 字串 | CONVERT(nvarchar(4000), EmployeeID, 126) |
fixed14.4 | N/A(XPath 中沒有相當於固定 14.4 XDR 資料類型的資料類型 ) | CONVERT(money, EmployeeID) |
date | 字串 | LEFT(CONVERT(nvarchar(4000), EmployeeID, 126, 10) |
time time.tz |
字串 | SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126, 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24) |
日期和時間轉換的設計目的是使用 SQL Serverdatetime 數據類型或 字串,將值儲存在資料庫中。 請注意,SQL Serverdatetime 資料類型不會使用 時區 ,且精確度小於 XML 時間 數據類型。 若要包含 時區 數據類型或其他精確度,請使用 字串 類型將數據儲存在 SQL Server 中。
當節點從其 XDR 數據類型轉換成 XPath 數據類型時,有時需要額外的轉換(從一個 XPath 數據類型轉換成另一個 XPath 數據類型)。 例如,請考慮此 XPath 查詢:
(@m + 3) = 4
如果 @m 是 固定的 14.4 XDR 資料類型,則會使用下列方式完成從 XDR 資料類型轉換成 XPath 資料類型的轉換:
CONVERT(money, m)
在此轉換中,節點會從 fixed14.4 轉換為 money。m
不過,新增 3 的值需要額外的轉換:
CONVERT(float(CONVERT(money, m))
XPath 運算式會評估為:
CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)
如下表所示,這是套用至其他 XPath 表達式的相同轉換(例如常值或複合表達式)。
X 未知 | X 為字串 | X 為數位 | X 為布爾值 | |
---|---|---|---|---|
string(X) | CONVERT (nvarchar(4000), X, 126) | - | CONVERT (nvarchar(4000), X, 126) | CASE WHEN X THEN N'true' ELSE N'false' END |
number(X) | CONVERT (float(53), X) | CONVERT (float(53), X) | - | 當 X THEN 1 ELSE 0 END 時案例 |
布林值(X) | - | LEN(X) > 0 | X != 0 | - |
範例
A. 轉換 XPath 查詢中的數據類型
在針對批注式 XSD 架構指定的下列 XPath 查詢中,查詢會選取 所有 Employee 節點,其 EmployeeID 屬性值為 E-1,其中 “E-” 是使用 sql:id-prefix 註釋指定的前置 詞。
Employee[@EmployeeID="E-1"]
查詢中的述詞相當於 SQL 運算式:
N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'
因為 EmployeeID 是 XSD 架構中的其中一個標識碼(idref、idrefs、nmtoken、nmtokens 等)數據類型值,所以 EmployeeID 會使用先前所述的轉換規則轉換成字元串 XPath 數據類型。
CONVERT(nvarchar(4000), Employees.EmployeeID, 126)
“E-” 前置詞會新增至字串,然後結果會與 N'E-1'
進行比較。
B. 在 XPath 查詢中執行數個數據類型轉換
請考慮針對批注式 XSD 架構指定的這個 XPath 查詢: OrderDetail[@UnitPrice * @OrderQty > 98]
此 XPath 查詢會傳回滿足述詞 @UnitPrice * @OrderQty > 98
的所有 <OrderDetail> 元素。 如果在批註架構中使用固定的 14.4 數據類型標註 UnitPrice,則此述詞相當於 SQL 運算式:
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)
在轉換 XPath 查詢中的值時,第一次轉換會將 XDR 數據類型轉換成 XPath 數據類型。 由於 UnitPrice 的 XSD 數據類型是固定的 14.4,如上表所述,這是使用的第一個轉換:
CONVERT(money, OrderDetail.UnitPrice))
因為算術運算符會將其操作 數轉換成數位 XPath 數據類型,因此會套用第二個轉換(從一個 XPath 數據類型轉換成另一個 XPath 數據類型),其中值會轉換成 float(53) (float(53) 接近 XPath 數位 數據類型):
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))
假設 OrderQty 屬性沒有 XSD 資料類型,OrderQty 會在單一轉換中轉換成數位 XPath 資料類型:
CONVERT(float(53), OrderDetail.OrderQty)
同樣地,值 98 會 轉換成數位 XPath 資料類型:
CONVERT(float(53), 98)
注意
如果架構中使用的 XSD 數據類型與資料庫中的基礎 SQL Server 數據類型不相容,或執行不可能的 XPath 數據類型轉換,SQL Server 可能會傳回錯誤。 例如,如果 EmployeeID 屬性以 id-prefix 註釋標註,XPath Employee[@EmployeeID=1]
會產生錯誤,因為 EmployeeID 具有 id-prefix 註釋,而且無法轉換成 數位。