类型化的 XML 与非类型化的 XML 的比较
您可以创建 xml 类型的变量、参数和列。 您也可以将 XML 架构的集合与 xml 类型的变量、参数或列关联起来。 在这种情况下,xml 数据类型实例称作“类型化”的实例。 否则,XML 实例称作“非类型化”的实例。
格式正确的 XML 和 xml 数据类型
xml 数据类型可实现 ISO 标准的 xml 数据类型。 因此,它可以在非类型化的 XML 列中存储格式正确的 XML 1.0 版的文档以及具有文本节点和任意数量顶级元素的所谓的 XML 内容片段。 系统将检查数据格式是否正确,但不要求将列绑定到 XML 架构,并且拒绝在扩展意义上格式不正确的数据。 对于非类型化的 XML 变量和参数也是如此。
XML 架构
XML 架构提供以下信息:
**验证约束。**每当向类型化的 xml 实例赋值或修改这样的实例时,SQL Server 都将验证该实例。
**数据类型信息。**架构提供有关 xml 数据类型实例中属性和元素的类型的信息。 与非类型化的 xml 可以提供的操作语义相比,类型信息为实例中包含的值提供了更精确的操作语义。 例如,可以对十进制值执行十进制算术运算,而不能对字符串值执行十进制算术运算。 因此,与非类型化的 XML 相比,可以对类型化的 XML 存储进行更大程度的压缩。
选择类型化或非类型化的 XML
在下列情况下,使用非类型化的 xml 数据类型:
您没有对应于您的 XML 数据的架构。
您有架构,但不希望服务器验证数据。 当应用程序将数据存储到服务器之前会执行客户端验证时,临时存储对该架构而言无效的 XML 数据时,或在服务器上使用不支持的架构组件时,需要如此。
在下列情况下,使用类型化的 xml 数据类型:
您有对应于您的 XML 数据的架构,并且希望服务器根据 XML 架构验证您的 XML 数据。
您希望利用基于类型信息的存储和查询优化。
您希望在编译查询过程中更好地利用类型信息。
类型化的 XML 列、参数和变量可以存储 XML 文档或内容。 但是,在声明时必须使用标志指定是存储文档还是存储内容。 此外,必须提供 XML 架构集合。 如果每个 XML 实例都刚好有一个顶级元素,请指定 DOCUMENT。 否则,请使用 CONTENT。 查询编译器在查询编译期间的类型检查过程中使用 DOCUMENT 标志来推断单独的顶级元素。
创建类型化的 XML
必须先按照CREATE XML SCHEMA COLLECTION (Transact-SQL)注册 XML 架构集合,然后才能创建类型化的 xml 变量、参数或列。 接下来,您就可以将 XML 架构集合与 xml 数据类型的变量、参数或列关联起来。
在下列示例中,使用由两部分组成的名称命名约定指定 XML 架构集合名称。 第一部分是 AdventureWorks 架构名称,第二部分是 XML 架构集合名称。
示例:将架构集合与 xml 类型变量关联起来
下面的示例创建一个 xml 类型变量并将架构集合与其关联起来。 该示例中指定的架构集合已导入 AdventureWorks 数据库。
DECLARE @x xml (Production.ProductDescriptionSchemaCollection)
示例:为 xml 类型列指定架构
下面的示例创建一个包含 xml 类型列的表,并为该列指定了一个架构:
CREATE TABLE T1(
Col1 int,
Col2 xml (Production.ProductDescriptionSchemaCollection))
示例:将 xml 类型参数传递给存储过程
下面的示例将 xml 类型参数传递给存储过程,并为该变量指定一个架构:
CREATE PROCEDURE SampleProc
@ProdDescription xml (Production.ProductDescriptionSchemaCollection)
AS
注意有关 XML 架构集合的以下事项:
XML 架构集合只有在通过创建 XML 架构集合注册该集合的数据库中才可用。
如果从字符串转换到类型化的 xml 数据类型,则分析过程还将根据指定集合中的 XML 架构命名空间执行验证和类型化。
可以从类型化的 xml 数据类型转换到非类型化的 xml 数据类型,反之亦然。
有关在 SQL Server 中生成 XML 的其他方法的详细信息,请参阅创建 XML 数据的实例。 生成 XML 后,可以将其赋给 xml 数据类型变量,也可以将其存储在 xml 类型列中以进行其他处理。
在数据类型层次结构中,xml 数据类型显示在 sql_variant 和用户定义类型之下,但显示在所有内置类型之上。
示例:指定用于约束类型化的 xml 列的方面
对于类型化的 xml 列,可以对这样的列实施约束,使之仅允许存储每个实例的单独的顶级元素。 可以在创建了表以后通过指定可选的 DOCUMENT 方面来进行此操作,如以下示例中所示:
CREATE TABLE T(Col1 xml
(DOCUMENT Production.ProductDescriptionSchemaCollection))
GO
DROP TABLE T
GO
默认情况下,类型化的 xml 列中存储的实例作为 XML 内容而非 XML 文档存储。 这允许存储以下内容:
零个或多个顶级元素
顶级元素中的文本节点
还可以通过添加 CONTENT 方面显式指定此行为,如以下示例中所示:
CREATE TABLE T(Col1 xml(CONTENT Production.ProductDescriptionSchemaCollection))
GO -- Default
请注意,可以在定义 xml 类型(类型化的 xml)的任何位置指定可选的 DOCUMENT/CONTENT 方面。 例如,创建类型化的 xml 变量时,可以添加 DOCUMENT/CONTENT 方面,如下所示:
declare @x xml (DOCUMENT Production.ProductDescriptionSchemaCollection)
文档类型定义 (DTD)
可以使用 XML 架构类型化 xml 数据类型列、变量和参数,但不可使用 DTD 类型化它们。 但是,内联 DTD 既可用于非类型化的 XML,也可用于类型化的 XML,以便提供默认值,并将实体引用替换为其扩展形式。
可以通过使用第三方工具将 DTD 转换为 XML 架构文档,然后将 XML 架构加载到数据库中。
将类型化的 XML 从 SQL Server 2005 升级到 SQL Server 2008
SQL Server 2008 对 XML 架构支持(包括对宽松验证的支持)进行了多项扩展,改进了对 xs:date、xs:time 和 xs:dateTime 实例数据的处理,并新增了对列表和联合类型的支持。 大多数情况下,这些更改不会影响升级过程。 但是,如果您使用了 SQL Server 2005 中允许使用 xs:date、xs:time 或 xs:dateTime(或任何子类型)类型的值的 XML 架构集合,则在将 SQL Server 2005 数据库附加到更高版本的 SQL Server 时将执行以下升级步骤:
对于每个 XML 列,如果该列是使用包含特定元素或属性(这些元素或属性被类型化为 xs:anyType、xs:anySimpleType、xs:date 或其任何子类型、xs:time 或其任何子类型、xs:dateTime 或其任何子类型,或者属于包含上述任何类型的联合类型或列表类型)的 XML 架构集合进行类型化的,将会执行以下操作:
将禁用该列的所有 XML 索引。
将继续采用 Z 时区表示所有 SQL Server 2005 值,这是因为已针对 Z 时区将这些值规范化。
任何小于元年 1 月 1 日的 xs:date 或 xs:dateTime 值在重新生成索引或对包含该值的 XML 数据类型执行 XQuery 或 XML-DML 语句时都将导致运行时错误。
xs:date 或 xs:dateTime 方面中的任何负年份或 XML 架构集合中的默认值都将自动更新为基 xs:date 或 xs:dateTime 类型允许的最小值(例如,对于 xs:dateTime,则更新为 0001-01-01T00:00:00.0000000Z)。
请注意,即使 XML 数据类型包含负年份,仍可以使用简单的 SQL SELECT 语句来检索整个 XML 数据类型。 建议您用新的受支持范围内的年份替代负年份,或将相应元素或属性的类型更改为 xs:string。