【问题标题】:Inserting XML into SQL Server database and then querying it将 XML 插入 SQL Server 数据库,然后查询它
【发布时间】:2015-04-04 23:14:24
【问题描述】:

我有一个将 XML 数据插入 SQL Server 中的 XML 列的程序,我发现 SQL Server 正在更改插入时源 XML 数据的格式。这使得之后使用相同的源 XML 查询数据变得非常困难。

例如,一个非常简单的演示来展示问题:

INSERT INTO XMLRecord (XMLData) VALUES ('<Test></Test>')

Select * from XMLrecord

返回:

<Test />

现在,如果我尝试运行查询以查看我的初始 XML 是否存在于数据库中:

select count (*) as 'Count' from XMLRecord where cast (XMLData AS NVARCHAR(MAX)) = '<Test></Test>'

0 rows returned;

但是,如果源 XML 不包含“空”标签,则插入和搜索工作正常:

INSERT INTO XMLRecord (XMLData) VALUES ('<Test>Test Values</Test>')

Select * from XMLrecord

返回:

<Test>Test Values</Test>

现在,如果我尝试运行查询以查看我的初始 XML 是否存在于数据库中:

select count (*) as 'Count' from XMLRecord where cast (XMLData AS NVARCHAR(MAX)) = '<Test>Test Values</Test>'

1 rows returned;

我希望有人可以就如何使其发挥作用提供解决方案。如何获取源 XML 块(大小、内容等未知),将其插入数据库,然后在数据库中查询我刚刚插入的 XML 的完全匹配。

数据需要以 XML 格式存储在数据库中,因为我也将它用于许多其他 xQueries。

非常感谢。

【问题讨论】:

  • 如果要匹配确切的字符串,则需要将值存储为字符串而不是 XML。您仍然可以将其转换为 XQuery 的 XML。

标签: sql-server xml database


【解决方案1】:

Xml 数据类型只保证内容被保留。来自this MSDN reference

原生存储为 xml 数据类型

数据存储在保留数据的 XML 内容的内部表示中。此内部表示包括有关包含层次结构、文档顺序以及元素和属性值的信息。具体来说,会保留 XML 数据的 InfoSet 内容。有关 InfoSet 的更多信息,请访问http://www.w3.org/TR/xml-infosetInfoSet 内容可能不是文本 XML 的相同副本,因为未保留以下信息:无关紧要的空格、属性顺序、命名空间前缀和 XML 声明。

因此,如果您绝对需要保留原始 Xml 的形状和结构,则可能需要将其存储为 nvarchar(max) 并在需要执行 XQuery 时转换为 xml。如果转换为 xml 对您的用例来说不是太昂贵,您可以使用计算列来呈现 Xml 转换版本:

create table XMLRecord (
   XMLData nvarchar(max),
   XMLDataAsXml as cast(XMLData as xml)
)

INSERT INTO XMLRecord (XMLData) VALUES ('<Test></Test>')
INSERT INTO XMLRecord (XMLData) VALUES ('<Test>Test Values</Test>')

Select * from XMLrecord;
-- Returns records and shows Xml casted version is different for empty record
select count (*) as 'Count' from XMLRecord where cast (XMLData AS NVARCHAR(MAX)) = '<Test></Test>';
-- returns 1
select count (*) as 'Count' from XMLRecord where cast (XMLData AS NVARCHAR(MAX)) = '<Test>Test Values</Test>';
-- returns 1

select XmlDataAsXml.value('Test[1]', 'nvarchar(max)') from XmlRecord;
-- returns 2 rows, 1 with empty string and 1 with Test Values as expected

如果转换为 xml 的开销对您的需求来说太昂贵,您可能需要以两种格式(2 列)存储它。

【讨论】:

  • 谢谢 - 一些很棒的信息和想法可以继续。
【解决方案2】:

XMLNVARCHAR 是不同的数据类型;它们有不同的行为,将它们混合起来会使您的代码非常混乱。

您不能将 XML 与 =&gt; 等谓词进行比较,您必须使用 XQuery predicates.value

SELECT * FROM XmlRecord WHERE XmlData.value('/Test[1]', 'NVARCHAR(max)') = 'Test Values'

XQuery 表达式 /Test[1] 将提取您的第一个 &lt;Test&gt; 元素的内容,.value(..., 'NVARCHAR(max)') 会将其转换为 NVARCHAR,以便您可以使用 = 进行比较。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2011-09-06
    • 2011-01-16
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多