示例:联合类型的函数
例如,以下联合类型的 <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