创建 XML 数据的实例

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

本文说明了如何生成 XML 实例。

在 SQL Server 中,可以通过下列方式生成 XML 实例:

  • 对字符串实例进行类型转换。

  • 将 SELECT 语句与 FOR XML 子句结合使用。

  • 使用常量赋值。

  • 使用大容量加载。

类型转换字符串实例和二进制实例

可以将任何 SQL Server 字符串数据类型(如 [n][var]char[n]textvarbinaryimage)分析成 xml 数据类型,方法是将相应字符串以 CAST 或 CONVERT 方式转换成 xml 数据类型。 对非类型化的 XML 进行检查以确认其格式是否正确。 如果存在与 xml 类型关联的架构,也会执行验证。 有关详细信息,请参阅 类型化的 XML 与非类型化的 XML 的比较

XML 文档可以采用不同的编码方式(例如,UTF-8、UTF-16 和 Windows-1252)进行编码。 下面概述了有关字符串和二进制源类型与 XML 文档编码进行交互的方式以及分析器行为方式的规则。

由于 nvarchar 采用为双字节 Unicode 编码(例如 UTF-16 或 UCS-2),因此 XML 分析器会将字符串值作为双字节 Unicode 编码 XML 文档或片断来处理。 这意味着该 XML 文档需要以双字节 Unicode 编码方式进行编码,同时需要与源数据类型兼容。 UTF-16 编码 XML 文档可以具有 UTF-16 字节顺序标记 (BOM),但是它不需要,因为源类型的上下文显式指出 UTF-16 编码 XML 文档只能是双字节 Unicode 编码文档。

varchar 字符串的内容被 XML 分析器视为单字节编码 XML 文档/片断。 由于 varchar 源字符串具有相关联的代码页,因此如果 XML 本身没有明确指定编码方式,分析器将使用该代码页。如果 XML 实例具有 BOM 或编码声明,则该 BOM 或声明应当与代码页一致,否则分析器将会报告一个错误。

varbinary 的内容被视为码位流,它将直接被传递到 XML 分析器。 这样,XML 文档或片断就需要提供 BOM 或其他内联编码信息。 分析器将仅查看该流来确定编码方式。 这意味着 UTF-16 编码 XML 需要提供 UTF-16 BOM,不带 BOM 和编码声明的实例将被解释为 UTF-8。

如果事先不知道 XML 文档的编码方式,并且数据在转换到 XML 之前被作为字符串或二进制数据而不是 XML 数据来传递,则建议将数据作为 varbinary处理。 例如,当使用 OpenRowset() 从 XML 文件读取数据时,应该指定将数据作为 varbinary(max) 值读取:

SELECT CAST(x AS XML);
FROM OpenRowset(BULK 'filename.xml', SINGLE_BLOB) R(x);

SQL Server 在内部以一种使用 UTF-16 编码的高效二进制表示形式来表示 XML。 用户提供的编码不会保留下来,但在分析过程中会考虑。

类型转换 CLR 用户定义类型

如果 CLR 用户定义类型具有 XML 序列化,则该类型的实例可以显式转换为 XML 数据类型。 有关 CLR 用户定义类型的 XML 序列化的更多信息,请参阅 从 CLR 数据库对象进行 XML 序列化

类型化 XML 中的空格处理

在 SQL Server 中,如果元素内容中的空格出现在一组只有空格并由标记(如开始或结束标记)分隔的字符数据中,则认为其无关紧要,因此不对其进行实体化。 (忽略 CDATA 部分。)这种空格处理方式与万维网联盟 (W3C) 发布的 XML 1.0 规格中介绍的空格处理方式不同。 这是因为 SQL Server 中的 XML 分析程序只识别有限数量的 DTD 子集(在 XML 1.0 中定义)。 有关 SQL Server 中支持的有限 DTD 子集的更多信息,请参阅 CAST 和 CONVERT (Transact-SQL)

默认情况下,在 XML 分析器将字符串数据转换为 XML 时,如果存在下列任何一种情况,则 XML 分析器将丢弃无关紧要的空格:

  • 未对元素或其上级元素定义 xml:space 属性。

  • 某元素或其某一祖先元素上有效的 xml:space 属性具有默认值。

例如:

DECLARE @x XML;
SET @x = '<root>      <child/>     </root>';
SELECT @x;

结果如下:

<root><child/></root>

不过,您可以更改此行为。 若要为 xml DT 实例保留空格,请使用 CONVERT 运算符,并将其可选的 style 参数的值设置为 1。 例如:

SELECT CONVERT(xml, N'<root>      <child/>     </root>', 1);

如果未使用 style 参数,或将其值设置为 0,则转换 xml DT 实例时不保留无关紧要的空格。 有关在将字符串数据转换为 xml DT 实例时如何使用 CONVERT 运算符及其 style 参数的更多信息,请参阅 CAST 和 CONVERT (Transact-SQL)

示例:将字符串值转换为类型化的 xml 并将其赋给某列

下面的示例将包含 XML 片段的字符串变量转换为 xml 数据类型,然后将其存储在 xml 类型列中:

CREATE TABLE T(c1 int primary key, c2 xml);
GO
DECLARE  @s VARCHAR(100);
SET @s = '<Cust><Fname>Andrew</Fname><Lname>Fuller</Lname></Cust>';

下面的插入操作将字符串隐式转换为 xml 类型:

INSERT INTO T VALUES (3, @s);

可以使用 cast() 将字符串显式转换为 xml 类型:

INSERT INTO T VALUES (3, CAST(@s AS XML));

另外,也可以使用 convert(),如下所示:

INSERT INTO T VALUES (3, CONVERT(XML, @s));

示例:将字符串转换为类型化的 XML 并将其赋给某个变量

在下面的示例中,将字符串转换为 xml 类型并赋给 xml 数据类型的变量:

DECLARE @x XML;
DECLARE  @s VARCHAR(100);
SET @s = '<Cust><Fname>Andrew</Fname><Lname>Fuller</Lname></Cust>';
SET @x = CONVERT(XML, @s);
SELECT @x;

将 SELECT 语句与 FOR XML 子句结合使用

可以在 SELECT 语句中使用 FOR XML 子句以返回 XML 形式的结果。 例如:

DECLARE @xmlDoc XML;
SET @xmlDoc = (SELECT Column1, Column2
               FROM   Table1, Table2
               WHERE  <some condition>
               FOR XML AUTO)
...;

SELECT 语句将返回文本 XML 片段,该片段将在后面为 xml 数据类型变量赋值的过程中进行分析。

也可以在 FOR XML 子句中使用 TYPE 指令 ,直接返回 xml 类型的 FOR XML 查询结果:

DECLARE @xmlDoc XML;
SET @xmlDoc = (SELECT ProductModelID, Name
               FROM   Production.ProductModel
               WHERE  ProductModelID = 19
               FOR XML AUTO, TYPE);
SELECT @xmlDoc;

结果如下:

<Production.ProductModel ProductModelID="19" Name="Mountain-100" />...

在下面的示例中,将 FOR XML 查询的类型化的 xml 结果插入 xml 类型列中:

CREATE TABLE T1 (c1 int, c2 xml);
GO
INSERT T1(c1, c2)
SELECT 1, (SELECT ProductModelID, Name
           FROM Production.ProductModel
           WHERE ProductModelID = 19
           FOR XML AUTO, TYPE);
SELECT * FROM T1;
GO

有关 FOR XML 的更多信息,请参阅 FOR XML (SQL Server)

注意

SQL Server 会将 xml 数据类型实例作为不同服务器构造(例如使用 TYPE 指令或在其中使用 xml 数据类型从 SQL 列、变量和输出参数返回 XML 的 FOR XML 查询)的结果返回到客户端。 在客户端应用程序代码中,ADO.NET 访问接口请求以二进制编码形式从服务器发送此 xml 数据类型信息。 但是,如果使用的是不带 TYPE 指令的 FOR XML,则 XML 数据将作为字符串类型返回。 在任何情况下,客户端访问接口都始终能够处理其中任一种形式的 XML 内容。

使用常量赋值

可以在需要 xml 数据类型实例时使用字符串常量。 这与将字符串隐式 CAST 为 XML 相同。 例如:

DECLARE @xmlDoc XML;
SET @xmlDoc = '<Cust><Fname>Andrew</Fname><Lname>Fuller</Lname></Cust>';
-- Or
SET @xmlDoc = N'<?xml version="1.0" encoding="ucs-2"?><doc/>';

上面的示例中,将字符串隐式转换为 xml 数据类型,并将其赋给 xml 类型变量。

下面的示例将常量字符串插入 xml 类型列:

CREATE TABLE T(c1 INT PRIMARY KEY, c2 XML);
INSERT INTO T VALUES (3, '<Cust><Fname>Andrew</Fname><Lname>Fuller</Lname></Cust>');

注意

对于类型化的 XML,是针对指定的架构来验证 XML。 有关详细信息,请参阅 类型化的 XML 与非类型化的 XML 的比较

使用大容量加载

通过增强的 OPENROWSET (Transact-SQL) 功能,可以在数据库中大容量加载 XML 文档。 可以将文件中的 XML 实例大容量加载到数据库的 xml 类型列中。 有关实际示例,请参阅 批量导入和导出 XML 文档的示例 (SQL Server)。 有关加载 XML 文档的详细信息,请参阅 加载 XML 数据

本节内容

项目 说明
检索和查询 XML 数据 介绍了当 XML 实例存储在数据库中时未保留的部分。

另请参阅