您可能会尝试以下解决办法:
SELECT xCol.value('//author/last-name[1]', 'nvarchar(50)') LastName
FROM T
但是
,这不会纠正该错误
,因为在每个 XML 实例中都可能出现多个 节点
。下面的改写方式将会有效:
SELECT xCol.value('(//author/last-name)[1]', 'nvarchar(50)') LastName
FROM T
This query returns the value of the first element in each XML instance.
父轴
如果节点的类型无法确定,则它将成为 anyType,后者不会隐式转换为任何其他类型
。在使用父轴(例如,xCol.query('/book/@genre/../price'))进行导航的过程中,尤其会发生这种情况;该父节点类型被确定为 anyType。元素也可能被定义为 XML 架构中的 anyType。在这两种情况下,丢失更为精确的类型信息通常会导致静态类型错误,并且要求将原子值显式转换为它们的特定类型。
Data()、Text() 和 String() 访问器
XQuery 具有一个可从节点中提取标量的、类型化值的函数 fn:data(),一个可返回文本节点的节点测试 text(),以及可返回节点的字符串值的函数 fn:string()。它们的用法有时会引起混乱。下面是有关在
SQL Server 2005 中正确使用它们的准则。请考虑 XML 实例 12:
• 非类型化 XML:路径表达式 /age/text() 返回文本节点"12"。函数 fn:data(/age) 返回字符串值"12",fn:string(/age) 也是如此。
• 类型化 XML:对于任何简单的类型化 元素,表达式 /age/text() 都会返回静态错误。另一方面,fn:data(/age) 返回整数 12,而 fn:string(/age) 会产生字符串"12"。
联合类型的函数和运算符
由于类型检查,联合类型要求进行认真的处理。以下示例阐述了其中两个问题。
示例:联合类型上的函数
请考虑以下联合类型的 的元素定义
<xs:element name="r">
<xs:simpleType>
<xs:union memberTypes="xs:int xs:float xs:double"/>
</xs:simpleType>
</xs:element>
在 XQuery 上下文中,"average"函数 fn:avg (//r) 会返回静态错误,因为 XQuery 编译器无法对 fn:avg() 的参数中 元素的不同类型(xs:int、xs:float 或 xs:double)的值求和。为解决该问题,请将函数调用改写为 fn:avg(for $r in //r return $r cast as xs:double ?)。
示例:联合类型上的运算符
加法运算"+"要求精确的操作数类型,以至于表达式 (//r)[1] + 1 对上述元素 的类型定义返回静态错误。可以解决该问题的一种改写方式是 (//r)[1] cast as xs:int?+1,其中"?"表示具体取值 0 或 1。
SQL Server 2005 要求带有"?"的"cast as",因为任何转换都会由于运行时错误而产生空序列。
Value()、Nodes() 和 OpenXML()
可以在 SELECT 子句中对 XML 数据类型使用多个 value() 方法来生成提取值的行集。nodes() 方法会为所选的每个节点生成一个内部引用,以用于进一步查询。当行集具有多个列,并且用于生成行集的路径表达式可能比较复杂时,将 nodes() 和 value() 方法组合使用可能会更为有效。