在 SQL Server 本机客户端中使用 XML 数据类型

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

重要

已从 SQL Server 2022 (16.x) 和 SQL Server Management Studio 19 (SSMS) 中删除SQL Server Native Client(通常缩写为 SNAC)。 不建议在新应用程序开发工作中使用 SQL Server Native Client(SQLNCLI 或 SQLNCLI11)和旧版 Microsoft OLE DB Provider for SQL Server (SQLOLEDB)。 请在此后切换为使用新版 Microsoft OLE DB Driver (MSOLEDBSQL) for SQL Server 或最新版的 Microsoft OLE DB Driver for SQL Server。 对于作为 SQL Server 数据库引擎组件附带的 SQLNCLI (版本 2012 到 2019) ,请参阅此支持生命周期异常

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 Native Client OLE DB 访问接口

DBTYPE_XML是SQL Server Native Client OLE DB 访问接口中特定于 XML 的新数据类型。 此外,可以通过现有的 OLE DB 类型(DBTYPE_BYTES、DBTYPE_WSTR、DBTYPE_BSTR、DBTYPE_XML、DBTYPE_STR、DBTYPE_VARIANT 和 DBTYPE_IUNKNOWN)访问 XML 数据。 可使用以下格式从SQL Server Native Client OLE DB 提供程序行集中的列检索存储在 XML 类型的列中的数据:

  • 文本字符串

  • ISequentialStream

注意

SQL Server Native Client OLE DB 提供程序不包括 SAX 读取器,但 ISequentialStream 可以轻松地传递到 MSXML 中的 SAX 和 DOM 对象。

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

还可以通过常见接口(如 IRow::GetColumns、IRowChange::SetColumns 和 ICommand::Execute)检索、插入或更新行集中类型为 XML 的列中存储的数据 。 与检索情况类似,应用程序可以将文本字符串或 ISequentialStream 传递给SQL Server Native Client 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 终止),则会报告溢出错误。

注意

对于 NULL XML 值,不返回值。

XML 标准要求 UTF-16 编码的 XML,以便以字节顺序标记 (BOM) UTF-16 字符代码 0xFEFF 开头。 使用 WSTR 和 BSTR 绑定时,SQL Server Native Client不需要或添加 BOM,因为绑定隐含编码。 当使用 BYTES、XML 或 IUNKNOWN 绑定时,目的是为了在处理其他 XML 处理器和存储系统时提供简便性。 在此情况下,应向 UTF-16 编码的 XML 提供 BOM,并且应用程序无需关心实际编码,因为绝大多数的 XML 处理器(包括 SQL Server)会通过检查该值的前几个字节推导出编码。 使用 BYTES、XML 或 IUNKNOWN 绑定从 SQL Server Native Client 接收的 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 行集的添加和更改内容

SQL Server Native Client向许多核心 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 属性集的添加和更改内容

SQL Server Native Client向许多核心 OLE DB 属性集添加新值或更改。

DBPROPSET_SQLSERVERPARAMETER 属性集

为了通过 OLE DB 支持 xml 数据类型,SQL Server Native Client实现新的 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 Native Client向 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 接口的添加和更改内容

SQL Server Native Client向许多核心 OLE DB 接口添加新值或更改。

ISSCommandWithParameters 接口

为了通过 OLE DB 支持 xml 数据类型,SQL Server Native Client实现了许多更改,包括添加 ISSCommandWithParameters 接口。 这一新接口继承自核心 OLE DB 接口 ICommandWithParameters 。 除了从 ICommandWithParameters 继承的三种方法外; GetParameterInfoMapParameterNamesSetParameterInfo; ISSCommandWithParameters 提供用于处理服务器特定数据类型的 GetParameterPropertiesSetParameterProperties 方法。

注意

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

IColumnsRowset 接口

SQL Server Native Client将以下特定于SQL Server列添加到 IColumnRowset::GetColumnsRowset 方法返回的行集中。 这些列包含 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 Native Client ODBC 驱动程序

在 SQL Server Native Client ODBC 驱动程序中,对各种函数进行了大量更改以支持 xml 数据类型。

SQLColAttribute

SQLColAttribute 函数有三个新的字段标识符,包括SQL_CA_SS_XML_SCHEMACOLLECTION_CATALOG_NAME、SQL_CA_SS_XML_SCHEMACOLLECTION_SCHEMA_NAME和SQL_CA_SS _XML_SCHEMACOLLECTION_NAME。

SQL Server Native Client ODBC 驱动程序报告SQL_DESC_DISPLAY_SIZE列和SQL_DESC_LENGTH列的SQL_SS_LENGTH_UNLIMITED。

SQLColumns

SQLColumns 函数有三个新列,包括SS_XML_SCHEMACOLLECTION_CATALOG_NAME、SS_XML_SCHEMACOLLECTION_SCHEMA_NAME和SS_XML_SCHEMACOLLECTION_NAME。 现有的 TYPE_NAME 列用于指示 XML 类型的名称,而 XML 类型列或参数的 DATA_TYPE 为 SQL_SS_XML。

SQL Server Native Client ODBC 驱动程序报告COLUMN_SIZE和CHAR_OCTET_LENGTH值的SQL_SS_LENGTH_UNLIMITED。

SQLDescribeCol

当无法在 SQLDescribeCol 函数中确定列大小时,SQL Server Native Client ODBC 驱动程序报告SQL_SS_LENGTH_UNLIMITED。

SQLGetTypeInfo

SQL Server Native Client ODBC 驱动程序SQL_SS_LENGTH_UNLIMITED报告为 SQLGetTypeInfo 函数中 xml 数据类型的最大COLUMN_SIZE。

SQLProcedureColumns

SQLProcedureColumns 函数具有与 SQLColumns 函数相同的列添加。

SQL Server Native Client ODBC 驱动程序将SQL_SS_LENGTH_UNLIMITED报告为 xml 数据类型的最大COLUMN_SIZE。

支持的转换

当从 SQL 转换为 C 数据类型时,SQL_C_WCHAR、SQL_C_BINARY 和 SQL_C_CHAR 可全部转换为 SQL_SS_XML,但必须符合以下规定:

  • SQL_C_WCHAR:格式为 UTF-16,无字节顺序标记 (BOM),无空终止。

  • SQL_C_BINARY:格式为 UTF-16,无空终止。 向从服务器接收的数据添加一个 BOM。 如果服务器返回了空字符串,则仍然将 BOM 返回给应用程序。 如果缓冲区长度的字节数为奇数,则会正确地截断数据。 如果分块区返回了整个值,则可以将它们连接起来以重新构建正确的值。

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

当从 C 转换为 SQL 数据类型时,SQL_C_WCHAR、SQL_C_BINARY 和 SQL_C_CHAR 可全部转换为 SQL_SS_XML,但必须符合以下规定:

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

  • SQL_C_BINARY:不执行任何转换,数据将“按原样”传递到服务器。UTF-16 数据必须以 BOM 开头;否则,服务器可能无法正确识别编码。

  • SQL_C_CHAR:数据在客户端上转换为 UTF-16 并发送到服务器,就像 SQL_C_WCHAR 一样(包括添加 BOM)。 如果未在客户端代码页中对 XML 进行编码,则这可能导致数据损坏。

XML 标准要求 UTF-16 编码的 XML,以便以字节顺序标记 (BOM) UTF-16 字符代码 0xFEFF 开头。 使用SQL_C_BINARY绑定时,SQL Server Native Client不需要或添加 BOM,因为绑定隐含编码。 其目的是为了在处理其他 XML 处理器和存储系统时提供简便性。 在这种情况下,BOM 应包含 UTF-16 编码的 XML,应用程序无需关注实际编码,因为大多数 XML 处理器 (包括SQL Server) 通过检查值的前几个字节来推断编码。 使用 SQL_C_BINARY 绑定从 SQL Server Native Client 接收的 XML 数据始终使用 BOM 在 UTF-16 中编码,并且没有嵌入的编码声明。

另请参阅

SQL Server Native Client 功能
ISSCommandWithParameters (OLE DB)