MS SQL SERVER2005 XML 最佳实践11

本文介绍了在XQuery上下文中处理XML数据时遇到的问题及解决方案,包括如何处理联合类型元素、使用value()和nodes()方法提取XML数据,以及使用FORXML生成XML实例。

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

示例:联合类型的函数
例如,以下联合类型的 <r> 的元素定义:

  复制代码
<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() 的参数中的 <r> 元素的不同类型(xs:int、xs:float 或 xs:double)的值求和。为了解决此问题,请将函数调用重写为 fn:avg(for $r in //r return $r cast as xs:double ?)。

示例:联合类型的运算符
加法运算(“+”)要求使用精确类型的操作数。因此,表达式 (//r)[1] + 1 返回静态错误,该错误包含前面所述的 <r> 元素的类型定义。一个解决方法是将其重写为 (//r)[1] cast as xs:int? +1,其中“?”表示取值 0 或 1。SQL Server 2005 要求带有“?”的“cast as”,因为任何转换都可能由于运行时错误导致产生空序列。

Value()、Nodes() 和 OpenXML()
您可以在 SELECT 子句中对 xml 数据类型使用多个 value() 方法以生成所提取值的行集。nodes() 方法为可用于其他查询的每个所选节点生成一个内部引用。生成行集时,如果行集有多个列且用于生成行集的路径表达式比较复杂,结合使用 nodes() 和 value() 方法可能会更有效。

nodes() 方法生成特定 xml 数据类型的实例,每个实例的上下文都设置为不同的所选节点。这种 XML 实例支持 query()、value()、nodes() 和 exist() 方法,并可用于 count(*) 聚合。所有其他用法都会导致错误。

示例:使用 nodes()
假定您希望提取作者的名字和姓氏,而名字不是“David”。此外,您希望提取该信息作为一个包含两列 FirstName 和 LastName 的行集。通过使用 nodes() 方法和 value() 方法便可以完成该操作,如下所示:

  复制代码
SELECT nref.value('(first-name/text())[1]', 'nvarchar(50)') FirstName,       nref.value('(last-name/text())[1]', 'nvarchar(50)') LastNameFROM   T CROSS APPLY xCol.nodes('//author') AS R(nref)WHERE  nref.exist('first-name[. != "David"]') = 1
 

在此示例中,nodes('//author') 生成一个由对每个 XML 实例的 <author> 元素引用组成的行集。通过计算与那些引用相关的 value() 方法,即可获得作者的名字和姓氏。

SQL Server 2000 提供了通过使用 OpenXml() 从 XML 实例生成行集的功能。您可以指定行集的关系架构,以及如何将 XML 实例中的值映射到行集中的列。

示例:对 xml 数据类型使用 OpenXml()
可以通过使用 OpenXml() 重写上一个示例中的查询,如下所示。方法是创建一个游标,该游标将每个 XML 实例读取到 XML 变量,然后向其应用 OpenXML:

  复制代码
DECLARE name_cursor CURSORFOR   SELECT xCol    FROM   TOPEN name_cursorDECLARE @xmlVal XMLDECLARE @idoc intFETCH NEXT FROM name_cursor INTO @xmlValWHILE (@@FETCH_STATUS = 0)BEGIN   EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlVal   SELECT   *   FROM   OPENXML (@idoc, '//author')          WITH (FirstName  varchar(50) 'first-name',                LastName   varchar(50) 'last-name') R   WHERE  R.FirstName != 'David'   EXEC sp_xml_removedocument @idoc   FETCH NEXT FROM name_cursor INTO @xmlValENDCLOSE name_cursorDEALLOCATE name_cursor
 

OpenXml() 创建一个内存中的表示形式,并且使用工作表而不是查询处理器。它依赖于 MSXML 3.0 版的 XPath 1.0 版处理器,而不是 XQuery 引擎。工作表不在对 OpenXml() 的多个调用间共享(即使是在同一个 XML 实例上)。这就限制了它的可伸缩性。在未指定 WITH 子句时,可以通过 OpenXml() 访问 XML 数据的边缘表格式。另外,也可以通过它在单独的“overflow”列中使用其余的 XML 值。

将 nodes() 和 value() 函数结合起来可有效地使用 XML 索引。因此,与 OpenXml 相比,这种结合有更高的可伸缩性。

使用 FOR XML 从行集生成 XML
可以通过在 FOR XML 中使用新的 TYPE 指令,从行集生成 xml 数据类型实例。

可以将结果赋给 xml 数据类型列、变量或参数。另外,可以嵌套 FOR XML 以生成任何层次结构。这使得嵌套的 FOR XML 比 FOR XML EXPLICIT 更容易编写,但对于较深的层次结构,它的性能可能不太好。FOR XML 还引入了新的 PATH 模式。这个新模式指定某个列的值在 XML 树中的路径。

可以使用新的 FOR XML TYPE 指令,采用 SQL 语法来定义关系数据上的只读 XML 视图。可以使用 SQL 语句和嵌入式 XQuery 查询该视图,如下面的示例所示。另外,您还可以在存储过程中引用这些 SQL 视图。

示例:返回生成的 xml 数据类型的 SQL 视图
以下 SQL 视图定义对关系列 pk 和从 XML 列中检索到的书作者创建 XML 视图:

  复制代码
CREATE VIEW V (xmlVal) ASSELECT pk, xCol.query('/book/author')FROM   TFOR XML AUTO, TYPE
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值