可扩展标记语言 (XML) 作为一种与平台无关的数据表示形式已被广泛采用。它对于在松散耦合且完全不同的系统,以及各种企业到企业 (B2B) 应用和工作流范畴内交换信息是很有用的。数据交换已成为 XML 技术的主要驱动力之一。.
XML 在企业应用程序中的使用正日益广泛,它主要用于对半结构化和非结构化数据进行建模。文档管理就是这样的一种应用程序。像电子邮件这样的文档是半结构化性质的。如果文档以 XML 的形式存储在数据库服务器中,就可以开发功能强大的应用程序来根据文档内容检索文档、查询部分内容(例如查找标题包含单词“背景”的部分),以及查询文档聚合。如果存在能够生成和使用 XML 的应用程序,则这样的方案就变得可行了。例如,Microsoft Office 2003 系统允许用户以 XML 标记的形式生成 Word、Excel、Visio 和 Infopath 文档。
为什么使用关系数据库来存储 XML 数据? ?将 XML 数据存储在关系数据库中会给数据管理和查询处理带来好处。SQL Server 提供了强大的查询和修改关系数据的能力,而且已经扩展到查询和修改 XML 数据。这使得可以利用在过去的版本上所进行的投资,就如同基于成本的优化和数据存储领域一样。例如,关系数据库中的索引技术已经广为人知,而且已经扩展到用于索引 XML 数据,这样就可以使用基于成本的决策来优化查询。
?XML 数据可以与现有的关系数据和 SQL 应用程序进行互操作,这样就可以在需要进行数据建模而又不破坏现有的应用程序的系统中引入 XML。数据库服务器还提供了管理功能来管理 XML 数据(例如备份、恢复和复制)。
?这些功能促进了对 SQL Server 2005 中的原生 XML 支持的需求,从而解决了不断增加的 XML 使用的问题。SQL Server 2005 中的 XML 支持将给企业应用程序开发带来好处。
?下面几部分将概述 SQL Server 2000 和 2005 中的 XML 支持,描述一些推动 XML 使用的方案,并且详细讨论服务器端和客户端的 XML 功能集。
SQL Server 2000 中的 XML 支持这一部分简要概述了 SQL Server 2000 中的 XML 支持,以及随后发布的 SQLXML 客户端编程平台 Web 版,它提供了丰富的支持来将关系数据映射到 XML 数据或将 XML 数据映射到关系数据。
服务器端支持在服务器上,XML 数据可以从表生成,并通过在 SELECT 语句中使用 FOR XML 子句来查询结果。这对于数据交换和 Web 服务应用程序是很理想的。FOR XML 的逆函数是一个名为 OpenXML 的关系行集合生成器函数;它通过求 XPath 1.0 表达式的值来从 XML 数据提取值,并将其放到行集合的列中。应用程序使用 OpenXML 来“切碎”传入 XML 数据,并将其存放到表中,或者用于通过 T-SQL 语言进行的查询。
客户端支持SQL Server 2000 对客户端编程的支持称为 SQLXML。这项技术的核心是 XML 视图,它是 XML 架构和关系表之间的双向映射。SQL Server 2000 只支持 XDR 架构的映射,尽管在后续的 Web 版中增加了对 XSD 的支持。XML 视图允许使用 XPath 1.0 的一个子集来进行查询,其中,可以使用映射将路径表达式转换成底层表中的 SQL 查询,并且将查询结果打包成 XML 结果。
SQLXML 还支持您创建 XML 模板,这使得您可以创建带有动态部分的 XML 文档。在 XML 文档中,您可以嵌入 FOR XML 查询和/或映射查询之上的 XPath 1.0 表达式。在执行 XML 模板时,可以用查询的结果来替换查询块。通过这种方式,您可以创建带有某些静态内容和某些数据驱动的动态内容的 XML 文档。
在SQL Server 2000 中,有两种访问 SQLXML 功能的主要方法:
?SQLXMLOLEDB Provider。SQLXMLOLEDB Provider 是一个 OLE DB 提供程序,它通过 ADO 公开 Microsoft SQLXML 功能。
?HTTP 访问。SQL Server 2000 中的 SQLXML 功能也可以使用 SQLXML ISAPI 过滤器通过 HTTP 进行访问。通过使用我们的配置工具,您可以建立网站来检索传入请求,从而通过 HTTP 执行 XML 模板、XML 视图之上的 FOR XML 和 XPath 1.0 语句。
XML 支持的局限性服务器和客户端编程平台为基于表格和 XML 数据之间的映射生成和使用 XML 数据提供了丰富的支持。这能够相当好地处理结构化 XML 数据。在 SQLXML 中,查询语言是 XPath 1.0 的一个子集,并且有一些局限性。例如,不支持 descendant-or-self 轴 (//)。因此,在开发某些解决方案时会存在一定的限制。例如,不保存 XML 文档顺序,而这对于像文档管理这样的应用程序来说是非常关键的。此外,还不支持递归的 XML 架构。尽管存在这样一些局限性,但是客户端 SQLXML 和服务器 XML 功能还是在应用程序开发中得到了广泛的使用。SQL Server 2005 解决了许多这样的限制,扩展了关系 XML 交换功能,并且还提供了原生 XML 支持。
SQL Server 2005 中的 XML 支持概述这一部分简要概述了 SQL Server 2005 中增加的新的 XML 支持,它是通过.NET 框架 V2.0 中的支持和本机客户端数据访问(如 OLE DB)进行补充的。
XML 数据类型XML 数据模型具有一些特性,这些特性使得映射到关系数据模型非常困难,如果不是完全不可能的话。XML 数据具有可以递归的层次结构;关系数据库提供对层次数据(建模为外键关系)的弱支持。文档顺序是 XML 实例的固有属性,并且必须保存在查询结果中。这与关系数据形成了对比,关系数据是无序的,必须通过附加的排序列来强制进行排序。在查询时重新组合结果是很费力的,因为实际的 XML 架构将 XML 数据分解到大量的表中。
SQL Server 2005 引入了一种称为 XML 的本机数据类型。用户可以创建这样的表,它在关系列之外还有一个或多个 XML 类型的列;此外,还允许带有变量和参数。为了更好地支持 XML 模型特征(例如文档顺序和递归结构),XML 值以内部格式存储为大型二进制对象 (BLOB)。
SQL Server 2005 提供了 XML 架构集合,可以将其作为一种方法来以元数据的形式管理 W3C XML 架构。XML 数据类型可以与 XML 架构集合相关联,以便对 XML 实例强加架构限制。当 XML 数据与 XML 架构集合相关联时,它称为类型化的 XML;否则,就称为非类型化的 XML。在一个框架中可以同时容纳类型化的 XML 和非类型化的 XML,保留 XML 数据模型,并且强制采用 XML 语义进行查询处理。底层关系基础结构被广泛用于这一目的。它支持关系数据和 XML 数据之间的互操作,这为更广泛地采用 XML 功能开辟了道路。
XML 数据类型查询和数据修改可以使用 T-SQL SELECT 语句来检索 XML 实例。在 XML 数据类型中提供了五种内置的方法来查询和修改 XML 实例。
XML 数据类型的方法接受 XQuery,它是一种新出现的 W3C 标准语言(目前处于 Last Call(最后请求)状态),并且包括导航语言 XPath 2.0。也可以使用一种语言来修改 XML 数据,比如添加或删除子树和更新标量值。与一大组函数一起,嵌入式的 XQuery 和数据修改语言为处理 XML 数据提供了丰富的支持。
XQuery 类型系统与 W3C XML 架构类型是一致的。大多数 SQL 类型与 XQuery 类型系统是兼容的(例如,小数)。少数类型(例如,xs:duration)是以内部格式存储的,并且可以通过适当的解释来与 XQuery 类型系统兼容。
编译阶段检查 XQuery 表达式和数据修改语句的静态类型的正确性,并且在类型化 XML 的情况下使用 XML 架构来进行类型推理。如果表达式由于类型安全冲突而在运行时失败,则会产生静态类型错误。
XML 索引查询执行在运行时处理每个 XML 实例;如果 XML 值比较大或需要在表的许多行中对查询进行求值,则查询执行就会变得非常费时。因此提供了一种索引 XML 列的机制来加速查询。
B 树广泛用于建立关系数据的索引。XML 列的主 XML 索引在该列中 XML 实例的所有标记、值和路径上都创建一个 B 树索引。通过这种方式,可以有效地对 XML 数据中的查询进行求值,并且在保留文档顺序和文档结构的同时从 B 树重新组合 XML 结果。
可以在 XML 列中创建次 XML 索引来加速不同类别的常见查询:PATH 索引(用于基于路径的查询)、PROPERTY 索引(用于属性包的情况)和 VALUE 索引(用于基于值的查询)。
XML 架构处理XML 列、变量和参数可以根据 XML 架构的集合(它可能与另一个集合相关(例如,通过使用 )或不相关)有选择地进行类型化。每个类型化的 XML 实例都从它遵循的 XML 架构集合指定目标命名空间。数据库引擎在数据分配和修改时根据 XML 架构来验证实例的有效性。
XML 架构信息用于存储和查询优化。类型化的 XML 实例在内部的二进制表示中包含类型化的值,这与 XML 索引中的一样。通过这种方式,可以有效地处理类型化 XML 数据。
关系数据和 XML 数据的集成用户可以在同一个数据库中存储关系数据和 XML 数据。简而言之,数据库引擎除了知道如何遵循关系数据模型之外,还知道如何遵循 XML 数据模型。在升级到 SQL Server 2005 之后,关系数据和 SQL 应用程序仍然能够正常工作。在服务器上,可以将驻留在文件和文本或图像列中的 XML 数据移到 XML 数据类型的列中。通过使用 XML 数据类型的方法,可以建立 XML 列的索引,并对其进行查询和修改。
数据库利用现有的关系基础结构和引擎组件(例如存储引擎和查询处理器)来进行 XML 处理。例如,XML 索引可以创建 B 树,而且可以在 Showplan 输出中查看查询计划。通过集成到关系框架中,数据管理功能(如备份/恢复和复制)可用于 XML 数据。同样地,新的数据管理功能(如数据库镜像和快照隔离)可以处理 XML 数据类型,以提供无缝的用户体验。
结构化数据应该存储在表和关系列中。当应用程序需要执行细粒度查询和数据修改时,对于使用 XML 的半结构化数据和标记数据,XML 数据类型是比较合适的选择。
FOR XML 和 OpenXML 增强现有的 FOR XML 功能已经在几个方面得到了增强。它能够处理 XML 数据类型的实例和其他新的 SQL 类型,例如 [n]varchar(max)。
新的 TYPE 指令生成的 XML 数据类型实例可以分配给 XML 列、变量或参数,也可以使用 XML 数据类型的方法进行查询。这允许嵌套 SELECT ...FOR XML TYPE 语句。
PATH 模式允许用户指定出现列值的 XML 树中的路径,并且与上述嵌套一起使用时比 FOR XML EXPLICIT 更易于编写。
XSINIL 指令与 ELEMENTS 一起使用,可以将 NULL 映射到带有属性 xsi:nil="true" 的元素。另外,新的 ROOT 指令还允许在所有的 FOR XML 模式下指定根节点。新的 XMLSCHEMA 指令生成 XSD 内联架构。
OpenXML 的功能增强包括在 sp_preparedocument 中接受 XML 数据类型以及在行集中生成 XML 和新的 SQL 类型的列。
对 XML 数据类型的客户端访问客户端可以通过几种方式访问服务器中的 XML 数据。使用 ODBC 和 OLE DB 的本机 SQL 客户端访问以 Unicode 字符串的形式传递 XML 数据类型。OLE DB 还提供对流 Unicode 数据的 XML 数据类型的 ISequentialStream 访问。
托管访问通过 .NET 框架 V2.0 中的 ADO.NET 将 XML 数据作为一个名为 SqlXml 的新类进行传递。它支持一个名为 CreateReader() 的方法,该方法返回 XmlReader 实例来读取返回的 XML。同样地,数据集能够将 XML 数据类型的实例加载到中间层的列,中间层可以作为 XML 文档进行编辑,并且重新保存到 SQL Server。这两者都支持对服务器发出 SQL 查询,以检索在中间层操作的 XML 列。
在 SQL Server 2005 中,可以使用直接对 HTTP 终结点进行的SOAP 访问来查询、检索和修改 XML 数据。
本机和托管客户端技术都提供了新的接口来检索类型化 XML 列的 XML 架构集合。
带有 XQuery 的客户端 XML 支持除了使用 ADO.NET 来检索表并将结果存放到关系数据集中之外,您还可以使用 XQueryCommand 类将关系数据直接加载到中间层的 XML 文档。该类提供了一个中间层 XQuery 处理器,它能够将 T-SQL 语句作为 XQuery 语言的一部分嵌入。通过这种方式,您可以查询本地 XML 文件,也可以从 SQL Server 检索数据(直接从表或者通过数据库存储程序),再将数据构造成 XML 格式,然后将其加载到中间层 XML 文档。这大大简化了 SQL Server 中的查询,将查询结果构造成特定的 XML 格式,并使其流向业务合作伙伴,而不需要将数据加载到数据集来执行数据转换。
推动 XML 存储方案XML 数据变得越来越普遍.它可以表示客户数据,带有或不带有描述数据的 XML 架构均可。XML 数据和 XML 架构需要在一起进行管理。实际应用程序的 XML 架构通常比较复杂,因而将这样的 XML 架构映射到表和列是一项复杂的任务。当 XML 架构改变或新的架构加入系统时,长时间维护这样的映射是一件很麻烦的事情。通常,XML 数据存储在文件系统或数据库服务器的文本列中。文本列有数据管理方面的好处(例如,复制和备份/恢复),但是不提供任何基于数据的 XML 结构的查询支持。在具有原生 XML 支持的情况下,使用 XML 进行应用程序开发变得更快。
自定义属性管理一些应用程序(例如用户界面软件)允许用户从一组固定的属性中进行选择。而其他应用程序则允许用户定义他们自己感兴趣的属性。如果这样的自定义属性是以 XML 的格式存储的,它们就可以很好地进行管理。应用程序可以支持标量属性以外的属性:
?可以支持对象中的多值属性,例如,多个电话号码。
?可以支持复杂属性,例如,一个文档的作者属性可能是该作者的联系信息。
可以将对象属性存储在 XML 数据类型的列中并建立索引,从而提高查询处理的效率。
数据交换和工作流XML 允许采用平台无关的方式在应用程序之间交换数据。可以使用 XML 标记将这样的数据建模为消息。代替不断地分割和生成 XML 消息,以 XML 的格式存储消息是明智的。这正是数据流所需要的。到达工作流阶段的 XML 消息携带着当前的状态。每个消息都需要进行处理,处理的进展记录在 XML 内容中(如状态改变),然后将 XML 数据转发到工作流处理的下一个阶段。消息可能是不同类型的,甚至可能是半结构化的,并且有不同的 XML 架构与它们相关联,因此将它们映射到表并不总是一件轻而易举的事。
针对不同垂直领域(如金融数据和地理空间数据)的基于 XML 的标准正在形成。这些标准根据可以查询和更新的实例数据来描述数据的结构。通常,实际数据采用的是二进制形式,而 XML 数据提供关于它们的元数据信息。
举一个简单的例子,为了将一个输入参数表传送到存储程序或函数,应用程序首先将数据转换成 XML,然后将其作为一个 XML 数据类型参数进行传递。在存储过程或函数内,从 XML 参数重新生成行集。
文档管理假设有一个呼叫中心,它采用 XML 文档来维护患者记录和谈话。当患者发起呼叫时,呼叫中心希望恢复前面的谈话以设置传入呼叫的情景。这可以通过查询 XML 标记实现,从而给应用程序带来好处。此外,还可以方便地检索以前谈话的细节并记录当前的谈话。
像电子邮件之类的文档本质上是半结构化的。带有 XML 标记的文档正变得越来越容易创建,例如,使用 Office 2003。可以将这些 XML 文档存储在 XML 列中,并建立索引,进行查询和更新。因此,通过利用原生 XML 支持,开发人员可以做更多的事情。
SQL Server 2005 中的服务器端 XML 处理SQL Server 2005 支持包括提供一个数据库,在这个数据库中,您可以存储关系数据和 XML 数据。
XML 数据类型您可以使用普通的 CREATE TABLE 语句来创建带有 XML 列的表。然后就可以采用一种特别的方式来建立 XML 的索引。
非类型化的 XMLSQL Server 2005 XML 数据类型实现了 ISO SQL-2003 标准 XML 数据类型。因此,它不仅可以存储格式良好的 XML 1.0 文档,而且可以存储所谓的 XML 内容片段(带有文本节点和任意数目的顶层元素)。在对数据进行格式良好性检查时,并不要求将 XML 数据类型绑定到 XML 架构,但是格式不规范的数据将被拒绝。
当架构不是已知先验的 并且因此而导致基于映射的解决方案不可能实现时,就可以使用非类型化的 XML。如果架构是已知的,但映射到关系数据模型非常复杂并且难于维护,或者存在多个架构而且这些架构是后来根据外部要求绑定到数据的,也可以使用非类型化的 XML。
例:表中非类型化的 XML 列
下面的语句创建一个名为“docs”的表,该表带有整型主键“pk”和非类型化的 XML 列“xCol”:
CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not null)
也可以创建一个包含多个 XML 列或关系列、带主键或不带主键的表。
类型化的 XML如果 XML 架构集合中有描述 XML 数据的 XML 架构,就可以将 XML 架构集合与产生类型化 XML 的 XML 列相关联。可以使用 XML 架构来验证数据的有效性,在编译查询和数据修改语句时执行比非类型化的 XML 更精确的类型检查,以及优化存储和查询处理。
类型化的 XML 列、参数和变量可以存储 XML 文档或内容,可以在声明时将其指定为一个选项(分别为DOCUMENT 或 CONTENT,默认为 CONTENT)。此外,还必须提供 XML 架构集合。如果每个 XML 实例都正好有一个顶层元素,则指定 DOCUMENT;否则,使用 CONTENT。查询编译器在类型检查中使用 DOCUMENT 标记来推理 singleton 顶层元素。
例:表中的类型化 XML 列
XML 列、变量和参数可以绑定到一个 XML 架构集合(请参阅本文后面的“XML 架构处理”一节以获得更多的详细信息和示例)。假定 myCollection 代表这样一个集合。下面的语句创建一个表 XmlCatalog,带有使用 myCollection 进行类型化的 XML 列文档。类型化的 XML 列还被指定为接受 XML 片段,而不只是 XML 文档。
CREATE TABLE XmlCatalog ( ID INT PRIMARY KEY, Document XML(CONTENT myCollection)) 约束 XML 数据类型的列 ?
除了类型化一个 XML 列之外,还可以在类型化和非类型化的 XML 数据类型的列中使用关系(列或行)约束。大部分 SQL 约束同样可应用于 XML 列,值得注意的唯一例外是主键和外键约束,因为 XML 数据类型的实例是不兼容的。因此,可以指定 XML 列可为空或不可为空,提供默认值,并且在列中定义 CHECK 约束。例如,非类型化的 XML 列可以有 CHECK 约束来验证存储的 XML 实例是否符合 XML 架构。
在下列条件下使用约束:
?业务规则不能用 XML 架构表示。例如,花店的交付地址必须在其业务场所 50 英里的范围内,这可以编写成 XML 列中的一个约束条件。该约束条件可以包括 XML 数据类型的方法。
?约束条件涉及表中其他的 XML 或 非 XML 列。这样的一个例子就是,使 XML 实例中存在的 Customer (/Customer/@CustId) 的id 与整型 CustomerID 列中的值相匹配。
例:约束 XML 列
要确定<book>的<author>的<last-name> 不同于<author>的<first-name> ,可以指定下列 CHECK 约束:
CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not nullCONSTRAINT CK_name CHECK (xCol.exist('/book/author[first-name = last-name]') = 0))
文本编码SQL Server 2005 将 XML 数据存储为 Unicode (UTF-16)。从服务器检索的XML 数据,其结果也是 UTF-16 编码的。如果想要采用一种不同的编码方式,就需要在检索数据之后进行必要的转换,转换的方法有两种,一种是通过强制类型转换,另一种是在中间层执行转换。例如,可以在服务器上将 XML 数据强制转换成 varchar 类型,在这种情况下,数据库引擎会通过 varchar 类型的排序所确定的编码方式来序列化 XML。
存储 XML 数据可以通过多种方式为 XML 列、参数或变量提供 XML 值。
?作为隐式转换到 XML 数据类型的字符或二进制 SQL 类型。
?作为文件的内容。
?作为 XML 发布机制 FOR XML 的输出(带有生成 XML 数据类型实例的 TYPE 指令)
对提供的值进行格式良好性检查,并且允许存储 XML 文档和 XML 片段。如果数据没有通过格式良好性检查,则拒绝它,并发出一个适当的错误消息。
对于类型化的 XML,需要检查提供的值是否符合已注册到类型化 XML 列的 XML 架构集合的 XML 架构。如果该 XML 实例没有通过这种有效性验证,则拒绝它。此外,仅当 CONTENT 允许提供 XML 文档和内容时,类型化的 XML 中的 DOCUMENT 标记才将所接受的值限制为 XML 文档。
例:将数据插入非类型化的 XML 列
下列语句在表 docs 中新插入一行,其中在整型的 pk 列插入的值为 1,而在 XML 列插入的是 实例。 数据(作为字符串提供)被隐式地转换为 XML 数据类型,并且在插入的过程中进行格式良好性检查。
INSERT INTO docs VALUES (1, '<book genre="security" publicationdate="2002" ISBN="0-7356-1588-2"> <title>Writing Secure Code</title> <author> <first-name>Michael</first-name> <last-name>Howard</last-name> </author> <author> <first-name>David</first-name> <last-name>LeBlanc</last-name> </author> <price>39.99</price> </book>')
例:将来自文件的数据插入非类型化的 XML 列
如下所示的 INSERT 语句使用 OPENROWSET 读取文件 C:\temp\xmlfile.xml 的内容作为 BLOB。在表 docs 中新插入一行,值 10 作为主键,而 BLOB 作为 XML 列 xCol。格式良好性检查出现在文件内容分配到 XML 列时。
INSERT INTO docs SELECT 10, xCol FROM (SELECT * FROM OPENROWSET (BULK 'C:\temp\xmlfile.xml', SINGLE_BLOB) AS xCol) AS R(xCol)
例:将数据插入类型化的 XML 列
类型化的 XML 列需要 XML 实例数据指定用于对其进行类型化的 XML 架构的目标命名空间(该命名空间可以为空)。在下面的示例中,这是通过命名空间声明 xmlns=http://myDVD 来实现的。
INSERT XmlCatalog VALUES(2, '<?xml version="1.0"?> <dvdstore xmlns="http://myDVD"> <dvd genre="Comedy" releasedate="2003"> <title>My Big Fat Greek Wedding</title> <price>19.99</price> </dvd> </dvdstore>')
例:存储使用带有 TYPE 指令的 FOR XML 生成的 XML 数据
通过 TYPE 指令增强的 FOR XML 可以生成像 XML 数据类型实例这样的结果。结果 XML 可以分配到 XML 列、变量或参数。在下面的语句中,使用 FOR XML TYPE 生成的 XML 实例被分配给 XML 数据类型的变量 @xVar。可以使用 XML 数据类型的方法来查询变量。
DECLARE @xVar XML SET @xVar = (SELECT * FROM docs FOR XML AUTO,TYPE) 存储表示
XML 数据类型的实例存储在内部的二进制表示中,该表示是可流化的,并且经过了优化,从而可以更有效地进行解析。标记映射到整型值,而映射的值存储在内部表示中。这也产生了一些数据的压缩。
对于非类型化的 XML,节点值存储为 Unicode (UTF-16) 字符串,因此需要进行运行时类型转换才能执行操作。例如,为了求谓词 /book/price > 9.99 的值,必须将该书的价格值转换为小数。而对于类型化的 XML,值的编码类型为在 XML 架构中指定的类型。这使得数据的解析更加有效,并且还不必进行运行时转换。
存储的二进制形式被限制为每 XML 实例 2 GB,这可以适应大部分的 XML 数据。此外,XML 层次的深度还被限制为 128 层。
XML 数据的信息集内容被保留。但是,它不可能是与文本 XML 一模一样的副本,因为下列信息没有保留:无关紧要的空白、属性的顺序、命名空间前缀和 XML 声明。
数据建模考虑事项通常,关系数据类型和 XML 数据类型的列的组合比较适合数据建模。可以将 XML 数据中的一些值存储在关系列中,而将其余的值或全部的 XML 值存储在 XML 列中。这可以产生更好的性能和锁定特性。
对于 singleton 值(即单值属性),XML 数据中的值可以提升为同一个表中的计算列。多值属性需要单独的属性表,该表必须使用触发器进行填充和维护。查询需要直接针对属性表进行编写。
对于锁定和更新特性,存储在 XML 列中的 XML 数据的粒度是至关重要的。SQL Server 将相同的锁定机制用于 XML 和非 XML 数据。如果粒度比较大,则在多用户的情况下,为了更新而锁定大的 XML 实例会引起吞吐量的下降。而另一方面,严格的分解会失去对象的封装性并增加重新组合的成本。
查询和修改 XML 数据查询存储在 XML 列中的 XML 实例需要解析列中的二进制 XML 数据。与解析文本形式的 XML 数据相比,解析二进制的 XML 要快得多。XML 索引避免了重新解析,这将在“建立 XML 数据的索引”一节中进行讨论。
XML 数据类型中的方法如果感兴趣,可以检索全部 XML 值,也可以检索部分 XML 实例。这可以使用四个 XML 数据类型的方法来实现:query()、value()、exist() 和 nodes(),它们接受 XQuery 表达式作为参数。第五个方法 modify() 允许修改 XML 数据并接受 XML 数据修改语句作为输入。
query() 方法用于提取 XML 实例的部分。XQuery 表达式求值为一个 XML 节点列表。以这些节点中的每一个为根的子树按照文档顺序返回。结果类型为非类型化的 XML。
value() 方法从 XML 实例提取标量值。它返回 XQuery 表达式所求值的节点的值。该值被转换为 value() 方法的第二个参数所指定的 T-SQL 类型。
exist() 方法用于对 XML 实例进行存在性检查。如果 XQuery 表达式求值为非空节点列表,则返回 1;否则,返回 0。
nodes() 方法产生特定 XML 数据类型的实例,每个实例都将其上下文设置为 XQuery 表达式所求值的不同节点。特定的 XML 数据类型支持 query()、value()、 nodes() 和 exist() 方法,并且可以用于 count(*) 聚合和 NULL 检查。所有其他的使用都会产生错误。
modify() 方法允许修改 XML 实例的某些部分,例如添加或删除子树,或者更新标量值(如将书的价格从 9.99 替换为 39.99)。
例:使用 query() 方法
考虑下面的表 docs 的 XML 列 xCol 中的查询,它提取 元素下的任何位置的 id 为 123 的 元素。该查询也从整型主键列检索值。SELECT 列表中的 query() 方法会为生成 元素序列的表中的每一行进行求值, 元素及其子树是按照文档顺序进行检索的。对于每个 XML 实例,如果没有 id 为 123 的 元素或者其下没有 元素,则不会返回结果,也就是说,query() 方法的返回值为 NULL。
SELECT pk, xCol.query('/doc[@id = 123]//section') FROM docs
NULL 返回值可以在外部 SELECT 语句中过滤掉。或者也可以使用 exist() 方法,如下一个示例所示。
例:使用 exist() 方法
考虑下面的查询,它在表 docs 的 XML 列 xCol 中包括 query() 和 exist() 方法。exist() 方法求路径表达式 /doc[@id = 123] 的值,检查是否存在顶层 元素,该元素具有一个称为 id 的属性,且其值为 123。对于每个这样的行,SELECT 子句中的 query() 方法都会进行求值;在这个示例中,query() 方法在 元素下的任何位置都产生一个 元素序列。从 exist() 方法返回 0 的任何行都会被忽略。
SELECT xCol.query('/doc[@id = 123]//section') FROM docs WHERE xCol.exist ('/doc[@id = 123]') = 1
例:使用 value() 方法
下面的查询使用 value() 方法以 Unicode 字符串的形式提取文档第三部分的标题。结果的 SQL 类型的 nvarchar(max) 被指定为 value() 方法的第二个参数。XQuery 函数 data() 从 节点提取标量值。
SELECT xCol.value( 'data((/doc//section[@num = 3]/heading)[1])', 'nvarchar(max)') FROM docs
XQuery 语言众多的 XML 都来源于存储在文件系统、Web 服务或配置文件中的 Office 文档。事实上,以 XML 格式或作为虚拟 XML 文档生成的数据正在不断地增加。为了处理这些数量越来越多的数据,一种强大的查询语言 XQuery 应运而生。在 XQuery 语言规范(位于 http://www.w3.org/TR/xquery)中将选择 XQuery 的理由描述为:
?一种巧妙地使用 XML 结构的查询语言,可以跨各种数据表示查询,而不管这些数据是物理存储在 XML 中,还是通过中间件被视为 XML。该规范描述了一种称为 XQuery 的查询语言,它旨在能广泛应用于许多类型的 XML 数据源。
?XQuery 旨在满足 W3C XML 查询工作组 XML 查询 1.0 要求和 XML 查询用例中的用例所确定的要求。它是一种旨在使查询简洁易懂的语言。它还相当地灵活,可以查询大范围的 XML 信息源,其中包括数据库和文档。
?XQuery 还可以概括为如下表述:XQuery 语言之于 XML 正如 SQL 语言之于关系数据库。
内嵌于 T-SQL 的 Xquery 子集(位于 http://www.w3.org/TR/xquery/)是一种支持查询 XML 数据类型的语言。这种语言正在由 Worldwide Web Consortium (W3C) 进行开发(目前处于最后请求状态),所有主要的数据库厂商(包括 Microsoft 在内)都参与其中。我们的实现与 2003 年 11 月发布的 XQuery 草案是一致的。
XQuery 将 XPath 2.0 作为导航语言包括在内。SQL Server 2005 的 XQuery 实现提供了用于遍历节点 (for)、节点检查 (where)、返回值 (return) 和排序 (order by) 的构造。它也提供了用于在查询过程中重新进行数据构形的元素构造。
SQL Server 2005 还提供了用于 XML 数据类型的数据修改 (DML) 的语言构造(请参阅下面的“数据修改”一节以获得更多信息)。下面的示例演示了如何将 XQuery 用于 XML 数据类型。
例:使用 XQuery 中丰富的语言构造
下面的查询显示了如何一起使用几个 XQuery 语言构造。它从 id 为 123 的文档返回区域号为 3 和更高的区域中的标题,并将其包装在新标记 中。
SELECT pk, xCol.query(' for $s in /doc[@id = 123]//section where $s/@num >= 3 return <topic>{data($s/heading)}</topic>') FROM docs
“for”遍历 id 为 123 的<doc> 元素下的所有<section> 元素,并且将每个这样的<section> 元素绑定到变量 $s。“where”确保区域号(<section> 元素的 @num 属性)为 3 或更高。该查询按照文档顺序返回区域<heading> 中的值,并且将其包装在一个称为<topic> 的构造元素中。
查询编译和执行SQL 语句是由 SQL 解析器解析的。当它遇到 XQuery 表达式时,它就会跳转到 XQuery 编译器,然后编译 XQuery 表达式。这会产生一个查询树,并将其嫁接到整个查询的查询树上。
整个查询树会进行查询优化并产生物理查询计划,该计划是根据基于成本的评估得出的。Showplan 输出显示了大部分关系运算符和一些新的运算符(例如,用于 XML 处理的 UDX)。
查询执行与关系框架中的其余部分一样,都是面向元组的。在表 docs 的每一行上都求 WHERE 子句的值;这需要在运行时解析 XML BLOB 以求出 XML 数据类型方法的值。如果条件满足,则锁定行,然后在行中求 SELECT 子句的值。结果以 XML 数据类型的形式产生(用于 query() 方法),并且转换成指定的目标类型(用于 value() 方法)。
而如果该行不满足 WHERE 子句中的条件,它就会被忽略,执行转到下一行。
XML 数据修改SQL Server 2005 提供了用于数据修改的构造作为对 XQuery 的一个扩展。子树可以在指定的节点之前或之后插入,或者作为最左边或最右边的子节点插入。此外,子树也可以插入到父节点,在这种情况下,它成为父节点最右边的子节点。属性、元素和文本节点插入都支持。
支持删除子树。在这种情况下,整个子树就从 XML 实例中被移除。
标量值可以用新的标量值进行替换。
例:将子树插入 XML 实例
这个示例显示了 modify() 方法的使用,它将一个新的<section> 元素插入编号为 1 的 元素的右边。
UPDATE docs SET xCol.modify(' insert <section num="2"> <heading>Background</heading> </section> after (/doc/section[@num=1])[1]')
例:将这本书的价格更新为 $49.99
下面的更新语句将 ISBN 为 1-8610-0311-0 的书的<price> 替换为 $49.99。该 XML 实例是通过 XML 架构 http://myBooksinstance 进行类型化的,因而就有了 XML 数据修改语句中的命名空间声明。
UPDATE XmlCatalog SET Document.modify (' default namespace = "http://myBooks" replace value of (/bookstore/book[@ISBN= "1-8610-0311-0"]/price)[1] with 49.99') 类型检查和静态错误
XQuery 引入了类型检查。编译阶段检查 XQuery 表达式和数据修改语句的静态类型正确性,并且将 XML 架构用于类型推理(在类型化 XML 的情况下)。如果表达式在运行时由于类型安全冲突而失败,则会产生静态类型错误。静态错误的例子有:将一个字符串与一个整数相加、在操作需要单值的地方接收一个值序列,以及查询不存在的节点来查找类型化数据。对于因类型不匹配而导致的静态错误,显式转换到正确的类型是一种变通方法。XQuery 运行时错误被转换成空序列。
如果编译器不能确定在运行时是否保证有 singleton 元素,则需要 singleton 元素的定位步骤、函数参数和运算符(例如,eq)就会返回错误。这种问题常常因非类型化的数据而产生。例如,查找属性需要 singleton 父元素;顺序选择单个的父节点就足够了。
例:value() 方法中的类型检查
下面的查询是在非类型化的 XML 列中进行的,它需要 //author/last-name 中的顺序规范,因为 value() 方法需要 singleton 节点作为第一个参数。如果没有,则编译器就不能确定在运行时是否只出现一个<last-name> 节点。
SELECT xCol.value('(//author/last-name)[1]', 'nvarchar(50)') LastName FROM docs
通过求 node()-value() 组合的值来提取属性值可以不需要顺序规范,如下一个示例所示。
例:已知的 singleton 元素
如下所示的 nodes() 方法为每个<book> 元素生成单独的行。对<book> 节点求值的 value() 方法提取 @genre 的值,@genre 作为一个属性,是 singleton 元素。
SELECT nref.value('@genre', 'varchar(max)') LastName FROM docs CROSS APPLY xCol.nodes('//book') AS R(nref) 跨域查询
如果数据驻留在关系数据类型的列和 XML 数据类型的列的组合中,就可能需要编写查询来组合关系数据处理和 XML 数据处理。通过使用带有 TYPE 指令的 FOR XML,可以将关系列和 XML 列中的数据转换成 XML 数据类型的实例,并使用 XQuery 对其进行查询。相反地,可以从 XML 值生成行集,并且使用 T-SQL 来对其进行查询,如下面的“从 XML 数据生成行集”一节所示。
编写跨域查询的一个更加方便和有效的方法是,使用 SQL 变量的值,或者使用 XQuery 或 XML 数据修改表达式中的列:
?使用 sql:variable(),可以在 XQuery 或 XML DML 表达式中应用 SQL 变量的值。
?通过 sql:column(),可以在 XQuery 或 XML DML 上下文中使用来自关系列的值。
这种方法允许应用程序参数化查询,如下面的示例所示。Sql:column() 的用法与前者类似,并且还带来其他的好处。正如基于成本的查询优化器所确定的,可以使用列的索引来提高效率。此外,也可以使用计算列。
XML 和用户定义的类型不允许与 sql:variable() 和 sql:column() 一起使用。
例:使用 sql:variable() 的跨域查询
在这种查询中,<book> 元素的 ISBN 是使用 SQL 变量 @isbn 来传入的。代替使用常量,sql:variable() 提供 ISBN 的值,并且该查询可以用于搜索任何 ISBN,而不只是 ISBN 为 0-7356-1588-2 的 元素。
DECLARE @isbn varchar(20) SET @isbn = '0-7356-1588-2' SELECT xCol FROM docs WHERE xCol.exist ('/book[@ISBN = sql:variable("@isbn")]') = 1 从 XML 数据生成行集
在自定义属性管理和数据交换场景中,应用程序通常将 XML 数据的某些部分映射到行集。例如,为了将输入参数表传送到存储过程或函数,应用程序需要将数据转换成 XML,并且将其作为 XML 数据类型的参数传入。在存储过程或函数中,行集是从 XML 参数生成的。
SQL Server 2000 为此提供了 OpenXml()。它简化了从 XML 实例生成行集的过程,方法是指定行集的关系架构以及将 XML 实例内的值映射到行集中的列的方式。
另外,还可以使用 nodes() 方法来生成 XML 实例中的节点上下文,并且在 value()、query()、exist() 和 nodes() 方法中使用该节点上下文来生成所期望的行集。nodes() 方法接受 XQuery 表达式,在 XML 列的每个 XML 实例中对其进行求值,并且有效地使用 XML 索引。下一个示例演示如何将 nodes() 方法用于行集生成。
例:从 XML 实例提取属性
假定要提取名字不是“David”的作者的名和姓,将其作为由两列(FirstName 和 LastName)组成的一个行集。通过使用 nodes() 和 value() 方法,您可以达到此目的,如下所示:
SELECT nref.value('first-name[1]', 'nvarchar(50)') FirstName, nref.value('last-name[1]', 'nvarchar(50)') LastName FROM docs CROSS APPLY xCol.nodes('//author') AS R(nref) WHERE nref.exist('.[first-name != "David"]') = 1
在这个示例中,nodes('//author') 产生一个指向每个 XML 实例的 元素的引用的行集。作者的名和姓是通过对与这些引用有关的 value() 方法求值来获得的。要获得好的性能,需要建立 XML 列的索引,这是下一部分的主题。
建立 XML 数据的索引XML 数据是以内部二进制形式存储的,存储容量可以达到 2 GB。每个查询在运行时一次或多次地解析表中每一行的 XML BLOB。这会使查询处理的速度变得很慢。如果在工作负荷中常常需要进行查询,则建立 XML 列的索引是有好处的,不过,这样做必须考虑在修改数据的过程中维护 XML 索引的成本。
XML 索引是通过一个新的 DDL 语句在类型化和非类型化的 XML 列中创建的。这为该列中的所有 XML 实例创建了一个 B 树。XML 列中的第一个索引是“主 XML 索引”。通过这个索引,可以在 XML 列中支持三种类型的次 XML 索引来加速普通类的查询,如下一节所述。
主 XML 索引在基表(即定义 XML 列的表)的主键中,主 XML 索引需要聚集索引。它在 XML 节点的信息集项的一个子集中创建一个 B 树。B 树的列表示标记,例如元素和属性名称、节点值和节点类型。其他的列捕获 XML 数据中的文档顺序和结构,以及从 XML 实例的根节点到每个节点的路径,从而有效地对路径表达式进行求值。基表的主键在主 XML 索引中复制,以使索引行与基表行相关。
XML 架构中给定的标记和类型名称被映射为整数值,而映射值存储在 B 树中以优化存储。索引中的路径列按照相反的顺序(即从节点到 XML 实例的根)存储映射值的串联。当路径后缀已知时(在一个路径表达式中,如 //author/last-name),相反的表示使得可以匹配路径值。
如果对基表进行分区,则需要以相同的方式对主 XML 索引进行分区,也就是使用相同的分区函数和分区架构。
全部的 XML 实例都是从 XML 列检索的(SELECT * FROM docs 或 SELECT xCol FROM docs)。需要 XML 数据类型方法的查询使用主 XML 索引,从索引本身返回标量值或 XML 子树。
例:创建主 XML 索引
下面的语句在表 docs 的 XML 列 xCol 中创建一个名为 idx_xCol 的 XML 索引。
CREATE PRIMARY XML INDEX idx_xCol on docs (xCol) 次 XML 索引
一旦主 XML 索引创建完毕,就可以创建次 XML 索引来加速工作负荷中不同类的查询。三种类型的次 XML 索引 — PATH、PROPERTY 和 VALUE — 分别对基于路径的查询、自定义属性管理方案和基于值的查询有利。
?PATH 索引在主 XML 索引的列 (path, value) 中构建 B 树。该路径的值是通过计算路径表达式和节点的值得出的,如果提供了一个路径值,则也可以使用所提供的值。在已知 PATH 索引开始字段的情况下,查找 PATH 索引可以加速路径表达式的求值。最常见的情况是在 SELECT 语句的 WHERE 子句中对 XML 列使用 exist() 方法。
?PROPERTY 索引在主 XML 索引的列 (PK, path, value) 中创建 B 树,其中 PK 是基表的主键。此索引对 XML 实例中的属性值查找有利。
?最后,VALUE 索引在主 XML 索引的列 (value, path) 中创建一个 B 树。此索引对节点的值已知但是其路径没有准确地在查询中指定的查询有利。这通常出现在祖先或自身 (descendant-or-self) 轴查询中,例如,//author[last-name="Howard"],其中, 元素可以出现在层次的任何一层。它还可以出现在“wildcard”查询中,例如 /book [@* = "novel"],其中,查询查找具有“novel”属性值的 元素。此外,VALUE 索引还可用于对类型化的 XML 进行基于值的范围扫描。
可以容纳多达 128 层的 XML 层次;在插入和修改的过程中,如果 XML 实例包含更长的路径,则会被拒绝。
类似地,可以建立一个节点值的前 128 个字节的索引;系统中可以容纳更长的值,但是不会建立索引。
例:基于路径的查找
假定下面的查询在工作负荷中是常见的:
SELECT xCol FROM docs WHERE xCol.exist ('/book[@genre = "novel"]') = 1
路径表达式 /book/@genre 和值“novel”对应于 PATH 索引的键字段。因此,类型 PATH 的次 XML 索引有助于此工作负荷:
CREATE XML INDEX idx_xCol_Path on docs (xCol) USING XML INDEX idx_xCol FOR PATH
例:获取对象的属性
考虑下面的查询,它从表 T 的每一行检索书的“genre”、“title”和 ISBN 属性:
SELECT xCol.value ('(/book/@genre)[1]', 'varchar(50)'), xCol.value ('(/book/title)[1]', 'varchar(50)'), xCol.value ('(/book/@ISBN)[1]', 'varchar(50)') FROM docs
属性索引可用于这种情况,该索引创建如下:
CREATE XML INDEX idx_xCol_Property on docs (xCol) USING XML INDEX idx_xCol FOR PROPERTY
例:基于值的查询
在下面的查询中,祖先或自己轴 (//) 指定了部分路径,这样,基于 ISBN 值的查询就可以从 VALUE 索引的使用中受益:
SELECT xCol FROM docs WHERE xCol.exist ('//book[@ISBN = "1-8610-0157-6"]') = 1
VALUE 索引创建如下:
CREATE XML INDEX idx_xCol_Value on docs (xCol) USING XML INDEX idx_xCol FOR VALUE 内容索引
可以在 XML 列中创建全文本索引;这会建立 XML 值内容的索引而忽略 XML 标记。属性值不是全文本索引的(因为它们被认为是标记的一部分),而元素标记被用作标记边界。可以在 XML 列中创建 XML 和全文本索引,并且组合使用全文本搜索和 XML 索引。使用全文本索引作为第一个筛选器来缩小选择范围,接着再应用 XQuery 进一步筛选。
使用 CONTAINS() 和 XQuery contains() 的全文本搜索有不同的语义。后者是子字符串匹配,而前者是使用词根检索的标记匹配。
例:在 XML 列中创建全文本索引
在 XML 列中创建全文本索引的步骤与在其他 SQL 类型列中创建全文本索引的步骤是非常相似的。需要在基表中有一个唯一的键列。DDL 语句如下,其中,PK__docs__7F60ED59 是该表的单列主键索引:
CREATE FULLTEXT CATALOG ft AS DEFAULT CREATE FULLTEXT INDEX ON dbo.docs (xCol) KEY INDEX PK__docs__7F60ED59
例:组合全文搜索和 XML 查询
下面的查询检查 XML 值是否在书的标题中包含单词“Secure”:
SELECT * FROM docs WHERE CONTAINS(xCol,'Secure') AND xCol.exist('/book/title/text()[contains(.,"Secure")]') =1
CONTAINS() 方法使用全文本索引来产生一个 XML 值的子集,它包含文档中所有的单词“Secure”。exist() 子句确保单词“Secure”出现在书的标题中。
使用 XML 索引执行查询XML 索引可以加速查询的执行。查询总是针对 XML 列中的主 XML 索引进行编译(如果存在的话)。为整个查询(包括关系部分和 XML 部分)制订一个查询计划,该计划可以通过数据库引擎基于成本的优化器进行优化。根据查询优化器的成本估算来选择次 XML 索引。
XML 索引的目录视图目录视图用于提供关于 XML 索引的元数据信息。目录视图 sys.indexes 包含带有索引“type”3 的 XML 索引项。“name”列包含 XML 索引的名称。
XML 索引也记录在目录视图 sys.xml_indexes 中,它包含所有的 sys.indexes 列以及一些对 XML 索引有意义的特别的列。列“secondary_type”中的值 NULL 表示主 XML 索引,值“P”、“R”和“V”分别代表 PATH、PROPERTY 和 VALUE 次 XML 索引。
可以从表值函数 sys.fn_indexinfo() 中找到 XML 索引的空间使用。它提供的信息包括所占用的磁盘页数、按字节计算的平均行大小、记录数,以及其他包括 XML 索引在内的所有索引类型的信息。这些信息可用于每个数据库分区;XML 索引使用与基表相同的分区架构和分区函数。
例:XML 索引的空间使用
SELECT sum(Pages) FROM sys.fn_indexinfo ('docs', 'idx_xCol_Path' , DEFAULT, 'DETAILED')
这产生在表 T 的所有分区中 XML 索引 idx_xCol_Path 所占用的磁盘页数。如果没有 sum() 函数,则结果将会返回每个分区的磁盘页使用。
XML 架构处理在系统中,XML 架构是可选的。如前所述,没有绑定到 XML 架构的 XML 数据类型被认为是非类型化的;XML 节点值将作为 Unicode 字符串存储,而 XML 实例需要进行格式良好性检查。可以建立非类型化 XML 列的索引。
要类型化 XML,可以将 XML 数据类型与已注册到 XML 架构集合的 XML 架构相关联。新的 DDL 语句允许创建一个或多个 XML 架构可以注册到的 XML 架构集合。绑定到 XML 架构集合的 XML 列、参数或变量是根据该集合中的所有 XML 架构进行类型化的。在 XML 架构集合中,类型系统标识每个使用其目标命名空间的 XML 架构。
XML 实例中的每个顶层 XML 元素都必须指定它遵循的可能为空的目标命名空间。在插入和修改数据时,将根据每个顶层元素的目标命名空间对其进行有效性检查。二进制 XML 表示根据相关的 XML 架构信息对类型化值进行编码,并且是完整描述的,因此,与非类型化的 XML 相比,它的再解析效率更高一些。在 XML 索引中,还将对值进行适当的类型化(如果 /book/price 是在像 xs:decimal 这样的命名空间中定义的,则会存储为小数)。
在查询编译的过程中,使用 XML 架构进行类型检查,并且会因类型不匹配而引起静态错误。查询编译器还将 XML 架构用于查询优化。
数据库引擎的元数据子系统包含 XML 类型信息,例如 XML 架构集合和它们所包含的 XML 架构,以及基本 XSD 和关系类型系统之间的映射。几乎所有的 W3C XML 架构 1.0 规范(请参阅 http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ 和 http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/)都支持。XML 架构文档中的注释和注解都没有保留,并且不支持 key/keyref。
XML 架构集合XML 架构集合是一个元数据实体(通过关系架构定义作用域),并且包含一个或多个相关(例如,使用<xs:import>) )或不相关的 XML 架构。XML 架构集合中单独的 XML 架构是使用其目标命名空间进行标识的。XML 架构集合是安全的实体,大致与表类似。
XML 架构集合是使用 CREATE XML SCHEMA COLLECTION 语义创建的,提供一个或多个 XML 架构。然后可以使用 XML 架构集合来类型化 XML 列。这种设计产生了灵活的数据模型,其中,按照不同的 XML 架构类型化的 XML 可以存储在相同的列中。当 XML 架构的数量很大时,这尤其方便。此外,这种设计还支持对 XML 架构进行一定程度的扩展。
另外,类型化的 XML 列中的选项 DOCUMENT 或 CONTENT 分别指定了 XML 树或片段是否可以存储在 XML 列中。默认为 CONTENT。对于 DOCUMENT,每个 XML 实例都必须指定其顶层元素的目标命名空间,该 XML 实例就是按照这个命名空间来进行有效性检查和类型化的。而对于 CONTENT,每个顶层元素都可以指定 XML 架构集合中的任何一个目标命名空间。该 XML 实例按照出现在实例中的所有目标命名空间进行有效性检查和类型化。
例:创建 XML 架构集合
假定要使用带有目标命名空间 http://myBooks 的 XML 架构来类型化 XML 实例。可以创建一个 XML 架构集合 myCollection 并将该 XML 架构作为 myCollection 的内容,如下所示:
CREATE XML SCHEMA COLLECTION myCollection AS '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://myBooks" elementFormDefault="qualified" targetNamespace="http://myBooks"> <xsd:element name="bookstore" type="bookstoreType" /> <xsd:complexType name="bookstoreType"> <xsd:sequence maxOccurs="unbounded"> <xsd:element name="book" type="bookType" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="bookType"> <xsd:sequence> <xsd:element name="title" type="xsd:string" /> <xsd:element name="author" type="authorName" /> <xsd:element name="price" type="xsd:decimal" /> </xsd:sequence> <xsd:attribute name="genre" type="xsd:string" /> <xsd:attribute name="publicationdate" type="xsd:string" /> <xsd:attribute name="ISBN" type="xsd:string" /> </xsd:complexType> <xsd:complexType name="authorName"> <xsd:sequence> <xsd:element name="first-name" type="xsd:string" /> <xsd:element name="last-name" type="xsd:string" /> </xsd:sequence> </xsd:complexType> </xsd:schema>'
同时也为该 XML 架构注册到的 myCollection 创建了一个新的元数据实体。
修改 XML 架构集合ALTER XML SCHEMA COLLECTION 语句支持用新的顶层架构组件来扩展 XML 架构,并且还支持将新的 XML 架构注册到 XML 架构集合。下面的示例对此进行了演示。
例:改变 XML 架构集合
下面的语句显示了如何将具有目标命名空间 http://myDVD 的新 XML 架构添加到 XML 架构集合 myCollection 中:
ALTER XML SCHEMA COLLECTION myCollection ADD '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://myDVD" elementFormDefault="qualified" targetNamespace="http://myDVD"> <xsd:element name="dvdstore" type="dvdstoreType" /> <xsd:complexType name="dvdstoreType"> <xsd:sequence maxOccurs="unbounded"> <xsd:element name="dvd" type="dvdType" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="dvdType"> <xsd:sequence> <xsd:element name="title" type="xsd:string" /> <xsd:element name="price" type="xsd:decimal" /> </xsd:sequence> <xsd:attribute name="genre" type="xsd:string" /> <xsd:attribute name="releasedate" type="xsd:string" /> </xsd:complexType> </xsd:schema>' XML 架构集合的目录视图
XML 架构集合的 SQL 目录视图允许用户重新构造单独的 XML 架构命名空间的内容。XML 架构集合在目录视图 sys.xml_schema_collections 中枚举。XML 架构集合“sys”由系统定义,并且包含一些预定义的命名空间,这些命名空间可用于所有用户定义的 XML 架构集合,而不必显式地加载它们。该列表包含用于 xml、xs、xsi、fn 和 xdt 的命名空间。
值得一提的其他两个目录视图是:sys.xml_schema_namespaces,它枚举每个 XML 架构集合中的所有命名空间;sys.xml_components,它枚举每个 XML 架构中的所有 XML 架构组件。
内置函数 XML_SCHEMA_NAMESPACE() 接受关系架构和 XML 架构集合的名称,以及 XML 架构的目标命名空间(可选)。它返回包含该 XML 架构的 XML 数据类型实例。如果目标命名空间参数被省去,那么该内置函数返回的 XML 实例就会包含 XML 架构集合中除预定义 XML 架构以外的所有 XML 架构。
例:枚举 XML 架构集合中的 XML 命名空间
将下列查询用于 XML 架构集合“myCollection”:
SELECT XSN.name FROM sys.xml_schema_collections XSC JOIN sys.xml_schema_namespaces XSN ON (XSC.xml_collection_id = XSN.xml_collection_id) WHERE XSC.name = 'myCollection'