使用 XML 数据类型

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsAnalytics Platform System (PDW)

下载 OLE DB 驱动程序

SQL Server 2005 (9.x) 引入了 xml 数据类型,它可用于在 SQL Server 数据库中存储 XML 文档和片段。 xml 数据类型是 SQL Server 中的内置数据类型,在某些方面类似于其他内置类型(如 int 和 varchar)。 与使用其他内置类型一样,可以在创建表时将 xml 数据类型用作列类型,也可以将其用作变量类型、参数类型或函数返回类型,还可以将其用在 CAST 和 CONVERT 函数中 。

编程时的注意事项

XML 可以是自描述的,即可以根据需要包含一个 XML 标头来指定文档的编码,例如:

<?xml version="1.0" encoding="windows-1252"?><doc/>

XML 标准描述 XML 处理器如何通过检查文档的前若干个字节来检测用于文档的编码。 有时,应用程序指定的编码可能与文档指定的编码相冲突。 对于作为绑定参数传递的文档,SQL Server 将 XML 视为二进制数据,因此不执行转换,并且 XML 分析器可以使用在文档内指定的编码而不会出现问题。 然而,对于绑定为 WSTR 的 XML 数据,应用程序必须确保将文档编码为 Unicode。 此方案可能需要将文件加载到 DOM 中,同时将编码更改为 Unicode 并对文档进行序列化。 如果未完成此步骤,可能发生数据转换,导致 XML 无效或损坏。

当在文字中指定 XML 时,也可能发生冲突。 例如,下面的内容无效:

INSERT INTO xmltable(xmlcol) VALUES('<?xml version="1.0" encoding="UTF-16"?><doc/>')

INSERT INTO xmltable(xmlcol) VALUES(N'<?xml version="1.0" encoding="UTF-8"?><doc/>')

适用于 SQL Server 的 OLE DB 驱动程序

DBTYPE_XML 是 OLE DB Driver for SQL Server 中特定于 XML 的新数据类型。 此外,可以通过现有的 OLE DB 类型(DBTYPE_BYTES、DBTYPE_WSTR、DBTYPE_BSTR、DBTYPE_XML、DBTYPE_STR、DBTYPE_VARIANT 和 DBTYPE_IUNKNOWN)访问 XML 数据。 可按如下格式在适用于 SQL Server 的 OLE DB 驱动程序行集的列中检索 XML 类型的列中存储的数据:

  • 文本字符串

  • ISequentialStream

注意

适用于 SQL Server 的 OLE DB 驱动程序不包含 SAX 读取器,但 ISequentialStream 可在 MSXML 中轻松传递到 SAX 和 DOM 对象 。

ISequentialStream 须用于检索大型 XML 文档 。 用于其他大值类型的相同技术也适用于 XML。 有关详细信息,请参阅使用大型数据类型

还可以通过常见接口(如 IRow::GetColumns、IRowChange::SetColumns 和 ICommand::Execute)检索、插入或更新行集中类型为 XML 的列中存储的数据 。 与检索情况类似,应用程序可将文本字符串或 ISequentialStream 传递给适用于 SQL Server 的 OLE DB 驱动程序 。

注意

要通过 ISequentialStream 接口以字符串格式发送 XML 数据,必须通过指定 DBTYPE_IUNKNOWN 获取 ISequentialStream 并在绑定中将其 pObject 参数设置为 Null 。

当由于使用者缓冲区过小而导致已检索的 XML 数据被截断时,长度可能作为 0xffffffff 返回,这意味着长度为未知的。 此行为与将它实现为数据类型的行为一致,就是数据类型流式传输到客户端,但在实际数据之前不发送长度信息。 在某些情况下,如果提供程序已缓冲整个值(如 IRowset::GetData)且已执行数据转换,可能返回实际长度 。

服务器会将发送到 SQL Server 的 XML 数据视为二进制数据。 此行为防止发生任何转换并允许 XML 分析器自动检测 XML 编码。 这样,就可以接受更广泛的 XML 文档(例如,以 UTF-8 编码的文档)作为 SQL Server 的输入。

如果将输入 XML 绑定为 DBTYPE_WSTR,则应用程序必须确保已对其进行 Unicode 编码,以避免由于不必要的数据转换而可能导致损坏。

数据绑定和强制

下表描述将所列数据类型与 SQL Server xml 数据类型一同使用时出现的绑定和强制转换。

数据类型 到服务器

XML
到服务器

Non-XML
从服务器

XML
从服务器

Non-XML
DBTYPE_XML 传递6,7 错误1 确定11, 6 错误8
DBTYPE_BYTES 传递6,7 N/A2 成功 11,6 N/A 2
DBTYPE_WSTR 传递6,10 N/A 2 成功4,6,12 N/A 2
DBTYPE_BSTR 传递6,10 N/A 2 成功 3 N/A 2
DBTYPE_STR 成功6,9,10 N/A 2 成功5,6,12 N/A 2
DBTYPE_IUNKNOWN 通过 ISequentialStream 的字节流7 N/A 2 通过 ISequentialStream 的字节流11 N/A 2
DBTYPE_VARIANT (VT_UI1 | VT_ARRAY) 传递6,7 N/A 2 空值 N/A 2
DBTYPE_VARIANT (VT_BSTR) 传递6,10 N/A 2 成功3 N/A 2

1如果使用 ICommandWithParameters::SetParameterInfo 指定了除 DBTYPE_XML 以外的服务器类型,而取值函数类型为 DBTYPE_XML,那么就会在执行语句时出错(DB_E_ERRORSOCCURRED,参数状态为 DBSTATUS_E_BADACCESSOR);否则,数据发送到服务器,但服务器会返回错误,指明不存在将 XML 转换为参数的数据类型的隐式转换。

2超出本文的范围。

3格式为 UTF-16、无字节顺序标记 (BOM)、无编码规格,且无空终止。

4格式为 UTF-16、无 BOM、无编码规格,且空终止。

5格式为在客户端代码页中编码的带有空终止符的多字节字符。 从服务器提供的 Unicode 进行转换可能导致数据损坏,因此建议不要使用此绑定。

6可使用 BY_REF。

7UTF-16 必须以 BOM 开头。 否则,服务器可能无法正确地识别编码。

8在创建取值函数时或在提取时,可能进行验证。 此错误为 DB_E_ERRORSOCCURRED,绑定状态设置为 DBBINDSTATUS_UNSUPPORTEDCONVERSION。

9使用客户端代码页将数据转换为 Unicode,然后发送到服务器。 如果文档编码与客户端代码页不匹配,则可能发生数据损坏,因此强烈建议不要使用此绑定。

10始终向发送到服务器的数据添加一个 BOM。 如果数据的开头已具有 BOM,则缓冲区的开头可能具有两个 BOM。 服务器使用第一个 BOM 将编码识别为 UTF-16,然后放弃它。 第二个 BOM 将被解释为零宽度不间断空格字符。

11格式为 UTF-16、无编码规格,且向从服务器收到的数据添加一个 BOM。 如果服务器返回了空字符串,则仍将 BOM 返回给应用程序。 如果缓冲区长度的字节数为奇数,则正确截断数据。 如果分块区返回了整个值,则可将其进行连接,重新构建正确的值。

12如果缓冲区长度少于两个字符(即空间不够,不能包含空终止),则报告溢出错误。

注意

对于 NULL XML 值,不返回值。

XML 标准要求 UTF-16 编码的 XML,以便以字节顺序标记 (BOM) UTF-16 字符代码 0xFEFF 开头。 使用 WSTR 和 BSTR 绑定时,适用于 SQL Server 的 OLE DB 驱动程序不要求 BOM 或添加 BOM,因为绑定隐含了编码。 当使用 BYTES、XML 或 IUNKNOWN 绑定时,目的是为了在处理其他 XML 处理器和存储系统时提供简便性。 在此情况下,应向 UTF-16 编码的 XML 提供 BOM,并且应用程序无需关心实际编码,因为绝大多数的 XML 处理器(包括 SQL Server)会通过检查该值的前几个字节推导出编码。 对于使用 BYTES、XML 或 IUNKNOWN 绑定从适用于 SQL Server 的 OLE DB 驱动程序收到的 XML 数据,它们始终以 UTF-16 进行编码、带有 BOM 且未嵌入编码声明。

OLE DB 核心服务 (IDataConvert) 提供的数据转换不适用于 DBTYPE_XML 。

当向服务器发送数据时将执行验证。 应由应用程序处理客户端验证和编码更改。 建议不要直接处理 XML 数据,而应使用 DOM 或 SAX 读取器来处理该数据。

可绑定 DBTYPE_NULL 和 DBTYPE_EMPTY 用于输入参数,但不能用于输出参数或结果。 当将它们绑定用于输入参数时,状态必须设置为 DBSTATUS_S_ISNULL 或 DBSTATUS_S_DEFAULT。

可以将 DBTYPE_XML 转换为 DBTYPE_EMPTY 和 DBTYPE_NULL,并可以将 DBTYPE_EMPTY 转换为 DBTYPE_XML,但无法将 DBTYPE_NULL 转换为 DBTYPE_XML。 这与 DBTYPE_WSTR 相一致。

DBTYPE_IUNKNOWN 是支持的绑定(如上表中所示),但在 DBTYPE_XML 与 DBTYPE_IUNKNOWN 之间不存在转换。 DBTYPE_IUNKNOWN 不能与 DBTYPE_BYREF 一起使用。

OLE DB 行集的添加和更改内容

OLE DB Driver for SQL Server 在许多核心 OLE DB 架构行集中添加了新值或进行了更改。

COLUMNS 和 PROCEDURE_PARAMETERS 架构行集

在 COLUMNS 和 PROCEDURE_PARAMETERS 架构行集添加了以下列:

列名称 类型 说明
SS_XML_SCHEMACOLLECTION_CATALOGNAME DBTYPE_WSTR 在其中定义 XML 架构集合的目录的名称。 对于非 XML 列或非类型化的 XML 列,为 NULL。
SS_XML_SCHEMACOLLECTION_SCHEMANAME DBTYPE_WSTR 在其中定义 XML 架构集合的架构的名称。 对于非 XML 列或非类型化的 XML 列,为 NULL。
SS_XML_SCHEMACOLLECTIONNAME DBTYPE_WSTR XML 架构集合的名称。 对于非 XML 列或非类型化的 XML 列,为 NULL。

PROVIDER_TYPES 架构行集

在 PROVIDER_TYPES 架构行集中,xml 数据类型的 COLUMN_SIZE 值为 0,且 DATA_TYPE 为 DBTYPE_XML 。

SS_XMLSCHEMA 架构行集

所引入的新的架构行集 SS_XMLSCHEMA 可供客户端检索 XML 架构信息。 SS_XMLSCHEMA 行集包含以下列:

列名称 类型 说明
SCHEMACOLLECTION_CATALOGNAME DBTYPE_WSTR XML 集合所属的目录。
SCHEMACOLLECTION_SCHEMANAME DBTYPE_WSTR XML 集合所属的架构。
SCHEMACOLLECTIONNAME DBTYPE_WSTR 类型化的 XML 列的 XML 架构集合名称;否则为 NULL。
TARGETNAMESPACEURI DBTYPE_WSTR XML 架构的目标命名空间。
SCHEMACONTENT DBTYPE_WSTR XML 架构内容。

每个 XML 架构都按目录名称、架构名称、架构集合名称和目标命名空间统一资源标识符 (URI) 限定范围。 此外,还定义了新的 GUID,其名称为 DBSCHEMA_XML_COLLECTIONS。 SS_XMLSCHEMA 架构行集的限制数和受限列定义如下。

GUID 限制数 受限列
DBSCHEMA_XML_COLLECTIONS 4 SCHEMACOLLECTION_CATALOGNAME

SCHEMACOLLECTION_SCHEMANAME

SCHEMACOLLECTIONNAME

TARGETNAMESPACEURI

OLE DB 属性集的添加和更改内容

OLE DB Driver for SQL Server 在许多核心 OLE DB 属性集中添加了新值或进行了更改。

DBPROPSET_SQLSERVERPARAMETER 属性集

为通过 OLE DB 支持 xml 数据类型,适用于 SQL Server 的 OLE DB 驱动程序实现了新的 DBPROPSET_SQLSERVERPARAMETER 属性集,它包含下列值 。

名称 类型 说明
SSPROP_PARAM_XML_SCHEMACOLLECTION_CATALOGNAME DBTYPE_WSTR 在其中定义 XML 架构集合的目录(数据库)的名称。 由三部分组成的 SQL 名称标识符的一部分。
SSPROP_PARAM_XML_SCHEMACOLLECTION_SCHEMANAME DBTYPE_WSTR 架构集合内 XML 架构的名称。 由三部分组成的 SQL 名称标识符的一部分。
SSPROP_PARAM_XML_SCHEMACOLLECTIONNAME DBTYPE_WSTR 目录内 XML 架构集合的名称。由三部分组成的 SQL 名称标识符的一部分。

DBPROPSET_SQLSERVERCOLUMN 属性集

为支持在 ITableDefinition 接口中创建表,适用于 SQL Server 的 OLE DB 驱动程序向 DBPROPSET_SQLSERVERCOLUMN 属性集添加三个新列 。

名称 类型 说明
SSPROP_COL_XML_SCHEMACOLLECTION_CATALOGNAME VT_BSTR 对于类型化 XML 列,此属性是一个字符串,它指定在其中存储 XML 架构的目录的名称。 对于其他列类型,此属性返回空字符串。
SSPROP_COL_XML_SCHEMACOLLECTION_SCHEMANAME VT_BSTR 对于类型化 XML 列,此属性是一个字符串,它指定定义此列的 XML 架构的名称。
SSPROP_COL_XML_SCHEMACOLLECTIONNAME VT_BSTR 对于类型化 XML 列,此属性是一个字符串,它指定定义此值的 XML 架构集合的名称。

与 SSPROP_PARAM 值类似,所有这些属性都是可选的且默认值为空。 仅当指定 SSPROP_COL_XML_SCHEMACOLLECTIONNAME 时,才能指定 SSPROP_COL_XML_SCHEMACOLLECTION_CATALOGNAME 和 SSPROP_COL_XML_SCHEMACOLLECTION_SCHEMANAME。 在将 XML 传递到服务器时,如果包含这些值,则将针对当前数据库检查它们是否存在(有效性),并且针对架构检查实例数据。 在所有情况下,要使这些值有效,它们必须全部为空或全部添入这些值。

OLE DB 接口的添加和更改内容

OLE DB Driver for SQL Server 在许多核心 OLE DB 接口中添加了新值或进行了更改。

ISSCommandWithParameters 接口

为通过 OLE DB 支持 xml 数据类型,适用于 SQL Server 的 OLE DB 驱动程序实现了大量更改,包括添加 ISSCommandWithParameters 接口。 这一新接口继承自核心 OLE DB 接口 ICommandWithParameters 。 除了从 ICommandWithParameters 继承的三个方法(GetParameterInfo、MapParameterNames 和 SetParameterInfo),ISSCommandWithParameters 还提供 GetParameterPropertiesSetParameterProperties 方法,它们用于处理服务器特定的数据类型。

注意

ISSCommandWithParameters 接口也利用新的 SSPARAMPROPS 结构 。

IColumnsRowset 接口

适用于 SQL Server 的 OLE DB 驱动程序在 IColumnRowset::GetColumnsRowset 方法返回的行集中添加 SQL Server 特定的如下列 。 这些列包含 XML 架构集合的由三个部分组成的名称。 对于非 XML 列或非类型化 XML 列,所有这三列均取默认值 NULL。

列名称 类型 说明
DBCOLUMN_SS_XML_SCHEMACOLLECTION_CATALOGNAME DBTYPE_WSTR XML 架构集合所属的目录,

否则为 Null。
DBCOLUMN_SS_XML_SCHEMACOLLECTION_SCHEMANAME DBTYPE_WSTR XML 架构集合所属的架构。 否则为 Null。
DBCOLUMN_SS_XML_SCHEMACOLLECTIONNAME DBTYPE_WSTR 类型化 XML 列的 XML 架构集合的名称,否则为 NULL。

IRowset 接口

通过 IRowset::GetData 方法检索 XML 列中的 XML 实例 。 根据由客户端指定的绑定,可以将 XML 实例作为 DBTYPE_BSTR、DBTYPE_WSTR、DBTYPE_VARIANT、DBTYPE_XML、DBTYPE_STR、DBTYPE_BYTES 进行检索,或者通过 DBTYPE_IUNKNOWN 将其作为接口检索。 如果使用者指定 DBTYPE_BSTR、DBTYPE_WSTR 或 DBTYPE_VARIANT,则访问接口将 XML 实例转换为用户请求的类型,并将其放入在相应绑定中指定的位置。

如果使用者指定 DBTYPE_IUNKNOWN 并将 pObject 参数设置为 NULL,或将 pObject 参数设置为 IID_ISequentialStream,则提供程序将 ISequentialStream 接口返回到使用者,让其可流式处理该列之外的 XML 数据 。 然后,ISequentialStream 将 XML 数据作为 Unicode 字符流返回 。

当返回与 DBTYPE_IUNKNOWN 绑定的 XML 值时,访问接口将报告 sizeof (IUnknown *) 的大小值。 此行为与在将某列绑定为 DBTYPE_IUnknown 或 DBTYPE_IDISPATCH 时采用的方法,以及无法确定实际列大小时 DBTYPE_IUNKNOWN/ISequentialStream 采用的方式一致。

IRowsetChange 接口

使用者可以通过两种方法更新列中的 XML 实例。 第一种方法是使用提供程序创建的存储对象 ISequentialStream 。 使用者可调用 ISequentialStream::Write 方法直接更新提供程序返回的 XML 实例 。

第二种方法是通过 IRowsetChange::SetData 或 IRowsetChange::InsertRow 方法 。 使用这种方法,可以在类型为 DBTYPE_BSTR、DBTYPE_WSTR、DBTYPE_VARIANT、DBTYPE_XML 或 DBTYPE_IUNKNOWN 的绑定中,指定使用者缓冲区内的 XML 实例。

如果指定 DBTYPE_BSTR、DBTYPE_WSTR 或 DBTYPE_VARIANT,则提供程序将在适当的列中存储使用者缓冲区中的 XML 实例存储。

如果指定 DBTYPE_IUNKNOWN/ISequentialStream,且使用者未指定任何存储对象,则使用者必须提前创建 ISequentialStream 对象,将 XML 文档与此对象绑定,然后通过 IRowsetChange::SetData 方法将此对象传递给提供程序 。 使用者还可以创建存储对象,将 pObject 参数设置为 IID_ISequentialStream,创建 ISequentialStream 对象,然后将 ISequentialStream 对象传递给 IRowsetChange::SetData 方法 。 在这两种情况下,提供程序都可以通过 ISequentialStream 对象检索 XML 对象,然后将其插入适当的列中 。

IRowsetUpdate 接口

IRowsetUpdate 接口提供了用于延迟更新的功能 。 在使用者调用 IRowsetUpdate::Update 方法之前,供行集使用的数据不可用于其他事务 。

IRowsetFind 接口

IRowsetFind::FindNextRow 方法不使用 xml 数据类型 。 调用 IRowsetFind::FindNextRow 且 hAccessor 参数指定 DBTYPE_XML 列时,返回 DB_E_BADBINDINFO 。 此时不考虑正在搜索的列的类型。 对于任何其他绑定类型,如果要搜索的列属于 xml 数据类型,则 FindNextRow 将失败并返回 DB_E_BADCOMPAREOP 。

另请参阅

适用于 SQL Server 的 OLE DB 驱动程序功能
ISSCommandWithParameters (OLE DB)