【问题标题】:Inserting distinct values from XML into table将 XML 中的不同值插入表中
【发布时间】:2012-04-13 10:59:23
【问题描述】:

我有一个包含复杂主键的表。我还有一个 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)和不同的时间戳(我的 biz 逻辑需要的值),此查询将失败并显示以下错误消息:

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

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

【问题讨论】:

    标签: sql-server xml tsql service-broker


    【解决方案1】:

    在键上执行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 不同 实例。

    【讨论】:

    • 是的,这正是我所需要的!!!感谢您对属性的评论,我会考虑到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多