将XML插入SQL Server数据库,然后查询它

时间:2015-04-04 23:14:24

标签: sql-server xml database

我有一个程序将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上的EXACT匹配。

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

非常感谢。

2 个答案:

答案 0 :(得分:1)

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

  

原生存储为xml数据类型

     

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

因此,如果您绝对需要保留原始Xml的形状和结构,则可能需要将其存储为nvarchar(max)并在需要执行XQueries时强制转换为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列)存储它。

答案 1 :(得分:0)

XMLNVARCHAR是不同的数据类型;他们有不同的行为,混合起来会让你的代码变得混乱。

您无法将XML与=>等谓词进行比较,您必须使用.value之类的XQuery predicates

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

XQuery表达式/Test[1]将提取您的第一个<Test>元素的内容,而.value(..., 'NVARCHAR(max)')会将其转换为NVARCHAR,因此您可以使用=比较。