2010-03-09 47 views
3

在Sql Server中我使用XML类型列来存储消息。我不想存储重复的消息。Sql Server XML类型列重复条目检测

我只会为每个用户发送几条消息。我目前正在查询这些消息的表格,将XML转换为C#代码中的字符串。然后我将这些字符串与我即将插入的内容进行比较。

不幸的是,Sql Server漂亮地打印XML类型字段中的数据。存储到数据库中的内容不一定与您稍后返回的字符串完全相同。它在功能上是等效的,但可能已删除空格等。

是否有一种有效的方法来比较我正在考虑插入的XML字符串与已经在数据库中的字符串?另外,如果我检测到重复,我需要删除旧信息,然后插入替换。

+0

+1好问题!这是XML中棘手的方面之一 - 我不是一个简单的解决方案,恐怕...... – 2010-03-09 18:22:09

+0

失去了兴趣?找到更好的解决方案? – 2010-03-17 10:11:58

+0

@ p.marino:不,我没有完全失去兴趣。我想接受你的解决方案,但是存储数据库中已有内容的散列似乎并不正确。我几乎宁愿放弃使用XML类型字段,然后回到varchar。我会将此添加为“解决方案”,但我不会接受这一点。 – 2010-03-17 20:21:19

回答

2

0 - 添加一个哈希列到表

1 - 当你收到一个新的消息,将整个XML为大写,删除所有空格,并返回/换行,然后计算标准化的字符串的哈希值。

2 - 检查您是否已经有一行包含生成的哈希码。

  • 如果是的话,这是重复的,把它 相应
  • 如果不是这样,原来的XML与散列一起存储在一个新行
+0

迂腐笔记:由于哈希代码的值不是必须的,但如果使用SHA1或MD5或其他东西,则碰撞风险可以忽略不计。非迂腐的笔记:您甚至可以创建一个函数来执行此计算(也许是CLR),为该值创建一个计算列,并在计算列上创建一个唯一索引。 – erikkallen 2010-03-09 18:27:12

+1

@erikallen:不需要CLR函数,只需使用内置的HASHBYTES http://msdn.microsoft.com/en-us/library/ms174415.aspx – 2010-03-09 19:02:45

+0

我不认为我需要做字符串规范化,你的步骤1。我可以计算原始消息字符串的散列值,然后重复的比较仍然是准确的。我的重复测试是检测将要存储的原始消息的重复项。 (“你好”不应该等于“HELLO”)。 – 2010-03-09 20:52:57

0

一种解决方案是停止使用类型化的XML领域。将XML字符串存储到varchar类型的字段中。

我不太喜欢这个解决方案,但我也不太喜欢p.marino的解决方案。存储表中已存在行的散列似乎不正确。

0

如果您在表中的每一行上使用OPENXML并查询关键节点和/或关键属性的实际XML信息,该怎么办?但是,你需要逐行进行,我不认为OPENXML可以处理一整套表格行。

1

我不是100%确定您的具体实施,但这是我玩过的东西。作为一个存储过程的想法会做插入。插入消息表对现有消息进行基本检查(SQL 2008语法):

declare @messages table (msg xml) 
insert into @messages values 
('<message>You like oranges</message>') 
,('<message>You like apples</message>') 

declare @newMessage xml = '<message>You like apples</message>' 

insert into @messages (msg) 
select @newMessage 
where @newMessage.value('(message)[1]', 'nvarchar(50)') not in (
    select msg.value('(message)[1]', 'nvarchar(50)') 
    from @messages 
)