我有一个程序将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。
非常感谢。
答案 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)
XML
和NVARCHAR
是不同的数据类型;他们有不同的行为,混合起来会让你的代码变得混乱。
您无法将XML与=
,>
等谓词进行比较,您必须使用.value
之类的XQuery predicates:
SELECT * FROM XmlRecord WHERE XmlData.value('/Test[1]', 'NVARCHAR(max)') = 'Test Values'
XQuery表达式/Test[1]
将提取您的第一个<Test>
元素的内容,而.value(..., 'NVARCHAR(max)')
会将其转换为NVARCHAR
,因此您可以使用=
比较。