关于postgresql:使用多个唯一约束进行Postgres冲突处理

Postgres conflict handling with multiple unique constraints

我想使用insert .. on confict do update ..语法与一个对两列有唯一约束的表。 这可能吗?

例如 mytable对col1和col2有独立的唯一约束。

我可以写:

1
INSERT INTO mytable(col1, col2, col3) VALUES ('A', 'B', 0) ON CONFLICT DO NOTHING;

但是这不起作用:

1
2
3
INSERT INTO mytable(col1, col2, col3) VALUES ('A', 'B', 0)
ON CONFLICT
DO UPDATE SET col3 = EXCLUDED.col3 + 1;

错误:ON CONFLICT DO UPDATE需要推理规范或约束名称

这也行不通:

1
2
3
INSERT INTO mytable(col1, col2, col3) VALUES ('A', 'B', 0)
ON CONFLICT (col1, col2)
DO UPDATE SET col3 = EXCLUDED.col3 + 1;

错误:没有与ON CONFLICT规范匹配的唯一或排除约束

此语法似乎是针对两列而不是两个约束的单个复合唯一约束而设计的。

如果违反任何唯一约束,有没有办法进行条件更新? 这个问题如何在Postgres中关于2列中的一列冲突? 暗示但不提供语法。


当我们要求DO UPDATE时,ON CONFLICT子句需要一个唯一约束。 定义主键时,仅引用列名就足够了; 这是人们倾向于找到的主要例子。

你提到你对col1和col2有'独特的约束',所以我可能认为你的表定义与此类似:

1
2
3
4
5
CREATE TABLE mytable(      
    col1 VARCHAR UNIQUE,    
    col2 VARCHAR UNIQUE,    
    col3 INT
);

但是您的查询引用了复合约束; 而不是单独的约束。 修改后的表定义如下:

1
2
3
4
5
6
CREATE TABLE mytable2(  
    col1 VARCHAR UNIQUE,
    col2 VARCHAR UNIQUE,
    col3 INT,
    CONSTRAINT ux_col1_col2 UNIQUE (col1,col2)
);

可以使用上面的查询:

1
2
3
INSERT INTO mytable(col1, col2, col3) VALUES ('A', 'B', 0)
ON CONFLICT (col1, col2)
DO UPDATE SET col3 = EXCLUDED.col3 + 1;

您可以将此唯一约束引用为ON CONFLICT (col1, col2)ON CONFLICT ON CONSTRAINT ux_col1_col2

但等等,还有更多......

The idea is to keep a counter column up to date which matches on
either unique column, or insert zero if neither exists...

这是一条与你在这里不同的道路。"在任一唯一列上匹配"允许在两者上匹配,或者两者都匹配。 如果我理解你的意图,只需要一个标签并增加适用记录上的计数器。 所以:

1
2
3
4
5
6
7
8
9
10
CREATE TABLE mytable2(  
    col1 VARCHAR PRIMARY KEY,
    col3 INT
);
INSERT INTO mytable2(col1,col3)
SELECT incr_label,0
FROM (VALUES ('A'),('B'),('C')) AS increment_list(incr_label)
ON CONFLICT (col1)
DO UPDATE SET col3 = mytable2.col3 + 1
RETURNING col1,col3;