1

我有一个带有复杂主键的表。此外,我还有一个接收 XML 消息的 Service Broker 服务,该消息基本上如下所示:

  <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)和不同的时间戳(我的 biz 逻辑需要的值),此查询将失败并显示以下错误消息:

违反 PRIMARY KEY 约束“TableName”。无法在对象“dbo.TableName”中插入重复键。重复键值为 (1, 2, 3)。

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

4

1 回答 1

2

对键执行 agroup 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(). 根据xml 数据类型的限制,不能保证属性的顺序。

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

于 2012-04-13T11:46:03.797 回答