MS SQL SERVER2005 XML 最佳实践10

本文探讨XQuery中的类型检查原理,包括静态类型错误处理、单一性检查及如何避免常见错误。介绍如何通过正确使用XQuery函数处理类型化和非类型化XML数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误模型
语法不正确的 Xquery 表达式和 XML DML 语句会返回编译错误。编译阶段会检查 XQuery 表达式和 DML 语句的静态类型正确性,并针对类型化的 XML 使用 XML 架构进行类型推理。如果表达式在运行时由于类型安全冲突而失败,会引起静态类型错误。静态错误的示例包括将字符串添加到整数,以及在不存在的节点中查询类型化的数据。

与 W3C 标准有所不同的是,XQuery 运行时错误被转换为空序列。这些序列根据调用上下文,可以作为空 XML 或 NULL 传播到查询结果。

通过显式转换为正确的类型,用户可以解决静态错误的问题,尽管运行时转换错误将被转换为空序列。

下列部分详细介绍了类型检查。

单一性检查
如果编译器无法确定是否在运行时保证单一性,则要求单一性的位置步骤、函数参数和运算符将返回错误。此问题经常出现在非类型化数据上。例如,对属性的查找需要单一的父元素。选择单个父节点的序号即可满足需要。计算 node()-value() 组合以提取属性值可能不需要指定序号。如以下示例中所示。

示例:已知单一性
在此示例中,nodes() 方法为每个 <book> 元素生成一个单独的行。对 <book> 节点进行计算的 value() 方法提取 @genre 值,其作为属性,具有单一性。

  复制代码
SELECT nref.value('@genre', 'varchar(max)') LastNameFROM   T CROSS APPLY xCol.nodes('//book') AS R(nref)
 

XML 架构用于对类型化的 XML 进行类型检查。如果某个节点指定为 XML 架构中单一的节点,则编译器将使用该信息,并且不会发生任何错误。否则,需要选择单个节点的序号。特别的情况是,使用 descendant-or-self (//)(如在 /book//title 中)会丢失 <title> 元素的单一性基数推理,即使 XML 架构指定其如此。因此,您应该将其重写为 (/book//title)[1]。

对于类型检查,务必注意 //first-name[1] 和 (//first-name)[1] 之间的差异。前者返回一组 <first-name> 节点,其中每个节点都是其同级节点间最左侧的 <first-name> 节点。后者返回 XML 实例中按文档顺序的第一个单一的 <first-name> 节点。

示例:使用 value()
下面对非类型化的 XML 列的查询导致发生静态的编译错误。这是因为 value() 希望将一个单一节点作为第一个参数,而编译器无法确定在运行时是否将仅有一个 <last-name> 节点:

  复制代码
SELECT xCol.value('//author/last-name', 'nvarchar(50)') LastNameFROM   T
 

可以考虑下面的解决办法:

  复制代码
SELECT xCol.value('//author/last-name[1]', 'nvarchar(50)') LastNameFROM   T
 

但是,该解决办法不解决错误,因为在每个 XML 实例中可能会有多个 <author> 节点。采用下面的重写代码可以解决问题:

  复制代码
SELECT xCol.value('(//author/last-name/text())[1]', 'nvarchar(50)') LastNameFROM   T
 

此查询返回每个 XML 实例中第一个 <last-name> 元素的值。

parent 轴
如果无法确定节点的类型,它将成为 anyType。这不会隐式转换为任何其他类型。在使用 parent 轴(如 xCol.query('/book/@genre/../price'))进行导航的过程中,尤其会发生这种情况。父节点类型确定为 anyType。在 XML 架构中,也可以将元素定义为 anyType。在这两种情况下,丢失更为精确的类型信息经常会导致发生静态类型错误,并需要将原子值显式转换为其特定类型。

Data()、text() 和 string() 取值函数
XQuery 有一个从节点提取类型化标量值的函数 fn:data()、一个返回文本节点的节点测试 text(),以及一个返回节点的字符串值的函数 fn:string()。它们的用法容易混淆。以下是在 SQL Server 2005 中正确使用它们的准则。使用 XML 实例 <age>12</age> 进行说明。

非类型化的 XML:路径表达式 /age/text() 返回文本节点“12”。函数 fn:data(/age) 返回字符串值“12”,fn:string(/age) 也是如此。


类型化的 XML:对于任何简单的类型化的 <age> 元素,表达式 /age/text() 都返回静态错误。另一方面,fn:data(/age) 返回整数 12。fn:string(/age) 产生字符串“12”。


联合类型的函数和运算符
由于类型检查,联合类型要求进行小心地处理。下列示例中说明了其中两个问题。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值