我有一张带有复杂主键的表。我还有一个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)。
有没有办法只插入来自该邮件的最新时间戳的不同值?
答案 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不同 实例