ON CONFLICT ... DO UPDATE SET 因重复行而失败

时间:2021-06-09 13:31:10

标签: sql postgresql

我有下一个查询:

INSERT INTO loger(state, id, event_timestamp, other_event_timestamp)
VALUES 
   (1, 12, '2020-01-01T19:00:00.000Z', '2020-01-01T19:00:00.000Z'),
   (1, 12, '2020-01-01T19:00:00.000Z', '2020-01-01T19:00:00.000Z') 
    ON CONFLICT(id, event_timestamp) DO UPDATE SET state = excluded.state

在执行过程中失败并报错:

ERROR:  ON CONFLICT DO UPDATE command cannot affect row a second time

附言这些数据来自外部,所以我应该按原样将其传递给查询。

1 个答案:

答案 0 :(得分:5)

错误信息非常清楚。 ON CONFLICT 子句引用表中已有的行。这在 documentation:

中有解释 <块引用>

带有 ON CONFLICT DO UPDATE 子句的 INSERT 是一个“确定性”语句。这意味着该命令将不允许多次影响任何单个现有行;出现这种情况时会引发基数违规错误。 建议插入的行在受仲裁索引或约束约束的属性方面不应相互重复。

(我添加了突出显示。)

您可以通过在查询中进行一些操作将其减少到一行。例如,以下插入任意一行:

INSERT INTO loger (state, id, event_timestamp, other_event_timestamp)
    SELECT DISTINCT ON (id, event_timestamp) state, id, event_timestamp, other_event_timestamp
    FROM (VALUES (1, 12, '2020-01-01T19:00:00.000Z', '2020-01-01T19:00:00.000Z'),
                 (1, 12, '2020-01-01T19:00:00.000Z', '2020-01-01T19:00:00.000Z') 
         ) v(state, id, event_timestamp, other_event_timestamp)
    ORDER BY id, event_timestamp
    ON CONFLICT(id, event_timestamp) DO UPDATE SET state = excluded.state;

您还可以将代码构建为两个单独的 INSERT

相关问题