2012-04-13 83 views
1

我有一个复杂的主键的表。我也有,其接收基本上看起来像下面的XML消息的服务代理服务:插入从XML不同的值成表

<TableName> 
    <CHANGED key1="1" key2="2" key3="3" timestamp="00:00:01"/> 
    <CHANGED key1="1" key2="2" key3="3" timestamp="00:00:02"/> 
    <CHANGED key1="1" key2="2" key3="3" timestamp="00:00:03"/> 
    </TableName> 

我的目标是这些值插入表中。

我尝试以下查询:

INSERT INTO TableName (KEY1, KEY2, KEY3, TS) 
    SELECT 
     Tbl.Col.value('@*[1]', 'int'), 
     Tbl.Col.value('@*[2]', 'int'), 
     Tbl.Col.value('@*[3]', 'int'), 
     Tbl.Col.value('@*[4]', 'datetime') 
    FROM @MESSAGE.nodes('//CHANGED') Tbl(Col) 

但是,当我们有几个记录与同复杂的密钥(KEY1,KEY2,KEY3)和不同的时间戳记(价值我需要为我的商务逻辑)情况下,该查询失败,并显示以下错误消息:

违反PRIMARY KEY约束'TableName'。不能插入对象“dbo.TableName” 重复键。重复的密钥值是 (1,2,3)。

有没有一种方法可以从该消息中只插入不同的值和最新的时间戳?

回答

2

在密钥上执行group by并在timestamp(最小或最大?)上进行聚合。

INSERT INTO TableName (KEY1, KEY2, KEY3, TS) 
SELECT key1, key2, key3, MIN(ts) 
FROM 
    (
    SELECT 
     Tbl.Col.value('@key1', 'int') AS key1, 
     Tbl.Col.value('@key2', 'int') AS key2, 
     Tbl.Col.value('@key3', 'int') AS key3, 
     Tbl.Col.value('@timestamp', 'datetime') as ts 
    FROM @MESSAGE.nodes('//CHANGED') Tbl(Col) 
) AS M 
GROUP BY key1, key2, key3 

要想获得真正的安全,你应该使用,而不是position()属性名。据Limitations of the xml Data Type属性的顺序无法得到保证。

不保留XML实例中属性的顺序。当您查询存储在xml类型列中的XML实例时,结果XML中的 属性的顺序可能与原始XML 实例不同。

+1

是的,这正是我需要的!谢谢你对你的关于属性的评论,我会考虑到这一点。 – 2012-04-13 12:03:14