将XML中的不同值插入表中

时间:2012-04-13 10:59:23

标签: sql-server xml tsql service-broker

我有一张带有复杂主键的表。我还有一个Service Broker服务,它接收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)。

有没有办法只插入来自该邮件的最新时间戳的不同值?

1 个答案:

答案 0 :(得分: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()。根据{{​​3}},不保证属性的顺序。

  

不保留XML实例中的属性顺序。当你   查询存储在xml类型列中的XML实例的顺序   生成的XML中的属性可能与原始XML不同   实例