我有下一个查询:
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
附言这些数据来自外部,所以我应该按原样将其传递给查询。
答案 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
。