类型化 XML 与非类型化 XML 比较

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

您可以创建 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

在创建类型化 xml 变量、参数或列之前,必须先使用 CREATE XML SCHEMA COLLECTION (Transact-SQL) 注册 XML 架构集合。 接下来,您就可以将 XML 架构集合与 xml 数据类型的变量、参数或列关联起来。

在下列示例中,使用由两部分组成的名称命名约定指定 XML 架构集合名称。 第一部分是架构名称,第二部分是 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 架构加载到数据库中。

从 SQL Server 2005 升级类型化 XML

SQL Server 2008 (10.0.x) 对 XML 架构支持(包括宽松验证支持)进行了多项扩展,改进了对 xs:datexs:timexs:dateTime 实例数据的处理,并新增了对列表和联合类型的支持。 大多数情况下,这些更改不会影响升级过程。 但是,如果使用 SQL Server 2005 (9.x) 中的 XML 架构集合,且该架构集合允许使用 xs:datexs:timexs:dateTime 类型(或任何子类型)的值,则在将 SQL Server 2005 (9.x) 数据库附加到更高版本的 SQL Server 时将执行以下升级步骤:

  1. 对于每个 XML 列,如果该列是使用包含特定元素或属性(这些元素或属性被类型化为 xs:anyTypexs:anySimpleTypexs:date 或其任何子类型、 xs:time 或其任何子类型、 xs:dateTime 或其任何子类型,或者属于包含上述任何类型的联合类型或列表类型)的 XML 架构集合进行类型化的,将会执行以下操作:

    1. 将禁用该列的所有 XML 索引。

    2. 所有 SQL Server 2005 (9.x) 值将继续采用 Z 时区表示,这是因为已针对 Z 时区将这些值规范化。

    3. 对于任何小于元年 1 月 1 日的 xs:datexs:dateTime 值,在重新生成索引或对包含该值的 xml 数据类型执行 XQuery 或 XML-DML 语句时都将导致运行时错误。

  2. xs:datexs:dateTime 方面中的任何负年份或 XML 架构集合中的默认值都将自动更新为基 xs:datexs:dateTime 类型允许的最小值(例如,对于 xs:dateTime,则更新为 0001-01-01T00:00:00.0000000Z)。

即使包含负年份,仍可以使用简单的 Transact-SQL SELECT 语句来检索整个 xml 数据类型。 建议将负年份用新的受支持范围内的年份替代,或将相应元素或属性的类型更改为 xs:string

另请参阅