将字符串转换为XML并插入SQL Server

12

我们有一个SQL Server 2008 R2数据库表,其中一列存储了XML数据类型的VARCHAR数据。

现在我需要获取xml中的一些元素。

因此,我想先将存储为VARCHAR数据类型的xml转换为存储为xml数据类型的xml。

示例:

表A

Id(int) , ProductXML (varchar(max))

表格B

Id(int), ProductXML(XML)

我希望将来自表AProductXML转换成XML数据类型并插入到表B中。

我尝试使用如下所示的CAST()CONVERT()函数:

insert into TableB (ProductXML)
select CAST(ProductXML as XML) from TableA;

我尝试进行转换,但是出现了错误。

XML解析:无法切换编码

有没有办法将表中的varchar条目转换为XML条目?

关于XML:它非常庞大,包含许多节点,并且其结构会动态变化。

例如:一行可以具有一个产品的XML条目,而另一行可以具有多个产品的XML条目。

2个回答

34

请提供您的XML样本,因为以下所有内容都可以工作:

CONVERT(XML, '<root><child/></root>')
CONVERT(XML, '<root>          <child/>         </root>', 1)
CAST('<Name><FName>Carol</FName><LName>Elliot</LName></Name>'  AS XML)

根据 Microsoft 的文档,您可能需要将其先转换为 nvarchar 或 varbinary(如下所示):

您可以通过将 SQL Server 字符串数据类型(例如 [n] [var] char、[n] text、varbinary 和 image)强制转换(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),但是由于源类型的上下文使其清楚它只能是一个两个字节的 Unicode 编码文档,因此不需要 BOM。

varchar 字符串的内容由 XML 解析器视为一个字节编码的 XML 文档/片段。由于 varchar 源字符串具有关联的代码页,因此如果 XML 本身没有指定显式编码,则解析器将使用该代码页进行编码。如果 XML 实例具有 BOM 或编码声明,则 BOM 或声明需要与代码页一致,否则解析器将报告错误。

varbinary 的内容被视为传递直接到 XML 解析器的码点流。因此,XML 文档或片段需要在内联提供 BOM 或其他编码信息。解析器只会查看流以确定编码方式。这意味着采用 UTF-16 编码的 XML 需要提供 UTF-16 BOM,而没有 BOM 和没有声明的实例编码将被解释为 UTF-8。

如果 XML 文档的编码事先未知,并且数据在转换为 XML 之前作为字符串或二进制数据传递,建议将数据视为 varbinary。例如,当使用 OpenRowset()从 XML 文件中读取数据时,应将要读取的数据指定为 varbinary(max)值:

select CAST(x as XML) 
from OpenRowset(BULK 'filename.xml', SINGLE_BLOB) R(x)

SQL Server内部使用高效的二进制表示法来表示XML,该表示法使用UTF-16编码。用户提供的编码不会被保留,但在解析过程中会予以考虑。

解决方案:

CONVERT(XML, CONVERT(NVARCHAR(max), ProductXML))

谢谢!我仍在阅读您写的所有内容。XML实际上是动态变化的。它可以包含单个产品或多个产品的XML信息。我只是举了一个例子。实际上,它是一个记录表,其中存储了不同的日志数据(XML)。 - CodeNinja
数据库设置的编码是什么? - Darek
很抱歉,我对此还不熟悉。我运行了在网上找到的以下命令来查找数据库编码:SELECT DATABASEPROPERTYEX('DBName', 'Collation') SQLCollation; 我得到了“SQL_Latin1_General_CP1_CI_AS”,这是你要求的吗? - CodeNinja
是的,看起来没问题。我想知道你的源列是否使用了某种无法直接编码为Unicode的编码方式...编写一个C#实用程序来传输数据并识别正确的编码方式只需要几分钟时间。此外,你尝试过只使用一条记录吗? - Darek
不知道怎么错过了,但 XML 文件开头有 <?xml version="1.0" encoding="utf-16"?> ,现在你说的一切都有意义了。它是 utf-16 编码。你有什么想法可以继续进行吗? - CodeNinja
是的。现在很容易...只需使用CONVERT(XML, CONVERT(NVARCHAR(max), ProductXML)) - Darek

6
这对我有用:

这对我有用:

select CAST(REPLACE(CAST(column3 AS NVARCHAR(MAX)),'utf-8','utf-16') AS XML) from table

2
你正在替换一串字符,而不是文档的编码。 - Darek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接