PostgreSQL ON CONFLICT带有WHERE子句

16

Postgres的文档让人觉得WHERE子句可以作为ON CONFLICT条件:https://www.postgresql.org/docs/9.5/static/sql-insert.html

我还没有成功实现这个(如果可能的话)。以下是我尝试过的其中一种组合:

INSERT INTO friends (id, dob, frn, status, "groupId", 
"createdAt", "updatedAt") 
VALUES ('1da04305-68ef-4dc1-be6c-
826ab83a6479', '1937-06-01T08:29:08-07:00', 100001, 'New', 'bc1567bc-
14ff-4ba2-b108-4cb2e0f0f768', NOW(), NOW()) 
ON CONFLICT 
    WHERE frn=100001 DO NOTHING

frn没有任何限制,因此更简单的语法:

ON CONFLICT (frn) DO NOTHING

抛出数据库错误。我希望这只是一个简单的语法问题。


你想要达到什么目的?在 frn 上实现唯一性吗?如果是这种情况,你应该在 frn 上设置一个唯一约束。 - pozs
在groupId的上下文中,frn仅是唯一的。因此,frn和groupId的组合是唯一的,但是单独看frn并不是唯一的。 - smeckydev
然后,使用新的UPSERT,您只能执行ON CONFLICT(“groupId”,frn)。--如果您只想检查frn:没有高并发安全的解决方案。 - pozs
是的,如果我在表上添加一个排除约束,我认为那会起作用。我仍然很好奇在新的UPSERT中是否可以使用WHERE子句? - smeckydev
1个回答

30

WHERE子句是ON CONFLICT (constraint) DO UPDATE SET ...子句的下级,在尝试插入时,它只查看违反指定约束条件的单行。

一个语法上有效的例子:

INSERT INTO friends (
    id, 
    dob, frn, status,
    "groupId", "createdAt", "updatedAt"
) VALUES (
    '1da04305-68ef-4dc1-be6c-826ab83a6479',
    '1937-06-01T08:29:08-07:00', 100001, 'New',
    'bc1567bc-14ff-4ba2-b108-4cb2e0f0f768', NOW(), NOW()
) 
ON CONFLICT ("groupId", frn) DO UPDATE SET
    status='Revised', 
    "updatedAt"=NOW()
WHERE friends.status<>'Deleted';

或者作为一个操作示例


9
请注意,您可能希望将其编写为 WHERE friends.status <> 'Deleted',否则您很可能会收到“列引用"status"不明确”的错误提示。 - Klesun
1
@Klesun,我很高兴你在这个古老的帖子下添加了评论,并且恰好及时解决了我的问题! - AlastairG
@Klesun 如果 where 条件为假会发生什么?'DO NOTHING' 与 'duplicate key violation'。 - valijon
1
@valijon,它将是“什么也不做”。 - Klesun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接