XPath 数据类型 (SQLXML 4.0)

适用于: SQL Server Azure SQL 数据库

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(非数字)和 infinity 均未使用。 尝试将非数字字符串 转换为数字 ,并尝试除以零会导致错误。

XPath 转换

在您使用 OrderDetail[@UnitPrice > "10.0"] 之类的 XPath 查询时,隐式和显式数据类型转换可能会对查询的意义产生细微的变化。 因此,理解 XPath 数据类型的实现方式十分重要。 可以在 W3C 网站 http://www.w3.org/TR/1999/PR-xpath-19991008.html中找到 XPath 语言规范(XPath)版本 1.0 W3C 建议建议 1999 年 10 月 8 日。

XPath 运算符分为四个类别:

  • 布尔运算符(and、or)

  • 关系运算符 (<, , <>=, >=)

  • 相等运算符(=、!=)

  • 算术运算符(+、-、*、div、mod)

每个运算符类别都以不同方式转换其操作数。 XPath 运算符根据需要隐式转换其操作数。 算术运算符将其操作数转换为 数字,并生成数字值。 布尔运算符将其操作数转换为 布尔值,并生成布尔值。 关系运算符和相等运算符产生布尔值。 但是,根据其操作数的原始数据类型,这两种运算符具有不同的转换规则,如下表所示。

操作数 关系运算符 相等运算符
这两种操作数均为节点集。 如果仅在一个集中有一个节点并且第二个集中有一个节点,以便其 字符串 值的比较为 TRUE 时,才为 TRUE。 相同。
一个是节点集,另一个是 字符串 如果仅在节点集中存在节点,以便转换为数字时,将其与转换为数字字符串的比较为 TRUE,则为 TRUE。 如果仅在节点集中有节点,以便转换为 字符串时,才会将其与 字符串 进行比较,则为 TRUE。
一个是节点集,另一个是 数字 如果仅在节点集中存在节点,以便转换为 数字时,其与 数字 的比较为 TRUE,则为 TRUE。 相同。
一个是节点集,另一个是 布尔值 如果仅在节点集中存在节点,以便转换为布尔值,然后转换为数字时,将其与转换为数字布尔值进行比较为 TRUE,则为 TRUE。 如果仅在节点集中存在节点,以便转换为 布尔值时,该节点与 布尔 值的比较为 TRUE,则为 TRUE。
两者均不是节点集。 将两个操作数转换为 数字 ,然后进行比较。 将两个操作数均转换为常见类型,然后进行比较。 如果任一是布尔值,则转换为布尔值;如果任一为数字,则转换为布尔;否则,请转换为字符串

注意

由于 XPath 关系运算符始终将其操作数转换为 数字因此无法进行字符串 比较。 为了包含日期比较,SQL Server 2000 向 XPath 规范提供此变体:当关系运算符将字符串与字符串进行比较、将节点设置为字符串或字符串值节点集设置为字符串值节点集时,将执行字符串比较(而不是数字比较)。

节点集转换

节点集转换并非始终都是直观的。 节点集通过仅获取集中第一个 节点的字符串值转换为字符串 。 节点集通过将节点集转换为数字,然后将其转换为字符串,然后将字符串转换为数字 通过测试节点集是否存在,将节点集转换为 布尔 值。

注意

SQL Server 不对节点集执行位置选择:例如,XPath 查询 Customer[3] 表示第三个客户;SQL Server 不支持这种类型的位置选择。 因此,不会实现 XPath 规范中所述的 node-set-to-string 或 node-set-to-number 转换。 无论 XPath 规范指定“first”语义,SQL Server 都使用“any”语义。 例如,根据 W3C XPath 规范,XPath 查询Order[OrderDetail/@UnitPrice > 10.0]选择具有大于 10.0 的 UnitPrice 的第一个 OrderDetail 的订单。 在 SQL Server 中,此 XPath 查询选择具有大于 10.0 的 UnitPrice 的任何 OrderDetail 的订单。

转换为 布尔 值会生成存在测试;因此,XPath 查询 Products[@Discontinued=true()] 相当于 SQL 表达式“Products.Discontinued is not null”,而不是 SQL 表达式“Products.Discontinued = 1”。 若要使查询等效于后一个 SQL 表达式,请先将节点集转换为非布尔 类型,例如 数字。 例如,Products[number(@Discontinued) = true()]

因为如果运算符对于节点集中任一节点为 TRUE,则大多数运算符均定义为 TRUE;所以,在节点集为空时,这些运算的计算结果始终为 FALSE。 因此,如果 A 为空,则 A = BA != B 均为 FALSE,并且 not(A=B)not(A!=B) 均为 TRUE。

通常,如果数据库中该列的值不 为 null,则存在映射到列的属性或元素。 如果元素的任何子集存在,则映射到行的元素将存在。

注意

使用 is-constant 批注的元素始终存在。 因此,不能对 is-constant 元素使用 XPath 谓词。

当节点集转换为 字符串数字时,其 XDR 类型(如果有)在批注架构中检查,并且该类型用于确定所需的转换。

将 XDR 数据类型映射到 XPath 数据类型

节点的 XPath 数据类型派生自架构中的 XDR 数据类型,如下表所示(node EmployeeID 用于说明目的)。

XDR 数据类型 等效

XPath 数据类型
使用的 SQL Server 转换
Nonebin.base64bin.hex 空值 NoneEmployeeID
boolean boolean CONVERT(bit, EmployeeID)
number、int、float、i1、i2、i4、i8、r4、r8、ui1、ui2、ui4、ui8 数字 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 无(在 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日期时间 数据类型还是 字符串存储在数据库中。 请注意,SQL Server日期/时间 数据类型不使用 时区 ,精度小于 XML 时间 数据类型。 若要包括时区数据类型或其他精度,请使用字符串类型将数据存储在 SQL Server 中。

在某一节点从其 XDR 数据类型转换为 XPath 数据类型时,有时候可能需要执行附加的转换(从一个 XPath 数据类型转换为另一个 XPath 数据类型)。 例如,请考虑下面的 XPath 查询:

(@m + 3) = 4  

如果 @m 为固定的 14.4 XDR 数据类型,则使用以下命令完成从 XDR 数据类型到 XPath 数据类型的转换:

CONVERT(money, m)  

在此转换中,节点 mfixed14.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 为字符串 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) - CASE WHEN X THEN 1 ELSE 0 END
布尔值(X) - LEN(X) > 0 X != 0 -

示例

A. 在 XPath 查询中转换数据类型

在针对带批注的 XSD 架构指定的以下 XPath 查询中,查询选择所有 Employee 节点,其 EmployeeID 属性值为 E-1,其中“E-”是使用 sql:id 前缀注释指定的前缀

Employee[@EmployeeID="E-1"]

该查询中的谓词等效于 SQL 表达式:

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

由于 EmployeeID 是 XSD 架构中的 IDidref、idrefsnmtoken、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 可能会返回错误。 例如,如果使用 ID 前缀批注对 EmployeeID 属性进行批注,则 XPath Employee[@EmployeeID=1] 将生成错误,因为 EmployeeID 具有 ID 前缀批注,无法转换为数字