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>'