共用方式為


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,對應到該資料行的屬性或元素通常存在。 如果任何資料列的子系存在,則對應到那些資料列的元素存在。

[!附註]

使用 is-constant 註解的元素永遠存在。 因此,無法在 is-constant 元素上使用 XPath 述詞。

當節點集轉換為 string 或 number 時,會在註解式結構描述中檢查其 XDR 類型 (如果有),並使用該類型判斷所需的轉換。

將 XDR 資料類型對應到 XPath 資料類型

節點的 XPath 資料類型衍生自結構描述中的 XDR 資料類型,如下表所示 (節點 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

number

CONVERT(float(53), EmployeeID)

id、idref、idrefsentity、entities、enumerationnotation、nmtoken、nmtokens、chardate、Timedate、Time.tz、string、uri、uuid

string

CONVERT(nvarchar(4000), EmployeeID, 126)

fixed14.4

N/A (在 XPath 中沒有相當於 fixed14.4 XDR 資料類型的資料類型)

CONVERT(money, EmployeeID)

date

string

LEFT(CONVERT(nvarchar(4000), EmployeeID, 126), 10)

time

time.tz

string

SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126), 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24)

不論系統使用 SQL Server datetime 資料類型或 string,將值儲存在資料庫中,日期和時間轉換的設計都適用。 請注意,SQL Server datetime 資料類型不會使用 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 的 EmployeeID 屬性值選取所有 Employee 節點,其中 "E-" 是使用 sql:id-prefix 註解所指定的前置詞。

Employee[@EmployeeID="E-1"]

查詢中的述詞相當於 SQL 運算式:

N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'

EmployeeID 是 XSD 結構描述中的其中一個 id (idref、idrefs、nmtoken、nmtokens 等等) 資料類型值,因此系統會使用先前描述的轉換規則,將 EmployeeID 轉換為 string XPath 資料類型。

CONVERT(nvarchar(4000), Employees.EmployeeID, 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 註解為 EmployeeID 屬性註解,XPath Employee[@EmployeeID=1] 會產生錯誤,因為 EmployeeID 包含 id-prefix 註解,而且無法轉換為 number。