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