当前位置: 首页 > 知识库问答 >
问题:

具有多个唯一约束的Postgres冲突处理

燕砚文
2023-03-14

我想用插页。。请务必更新。。对两列具有唯一约束的表的语法。这可能吗?

mytable对col1和col2有单独的唯一约束。

我可以写:

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

然而,这不起作用:

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

错误:冲突时,更新是否需要推理规范或约束名称

这也不起作用:

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

错误:不存在与冲突规范匹配的唯一或排除约束

这种语法似乎是为两列上的单一复合唯一约束而设计的,而不是两个约束。

如果违反了其中一个唯一约束,有没有办法进行条件更新?这个问题是如何在博士后的两个专栏中的一个专栏中突出冲突?暗指它,但没有提供语法。

共有2个答案

东郭宏深
2023-03-14

因为冲突目标不能是两个不同的唯一约束,所以您必须使用模拟的Upert并自行处理冲突。

--希望

在mytable(col1,col2,col3)中插入冲突DO更新集col3=EXCLUDED上的值('A','B',0)。col3-1;

WITH upsert AS (
  UPDATE mytable
  SET col1 = 'A', col2 = 'B', col3 = col3 + 1
  WHERE col1 = 'A' OR col2 = 'B'
  RETURNING *
)
INSERT INTO mytable (col1, col2, col3)
SELECT 'A', 'B', 0
WHERE NOT EXISTS (SELECT * FORM upsert);

此语句将生成包含A或B或两者的行,换句话说,满足col1上的唯一性和col2上的唯一性。

不幸的是,这个解决方案受到限制,即A和B之间必须有一些逻辑链接,否则如果插入('A', null),然后是(null, B),然后是(A, B),您将最终得到两行,都增加了第三个插入:

| col1 | col2 | col3 |
+------+------+------+
|    A | null |    1 |
| null |    B |    1 |
顾乐池
2023-03-14

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

您提到您对col1和col2有单独的唯一约束,所以我可能会假设您的表定义与此类似:

CREATE TABLE mytable(       
    col1 varchar UNIQUE,    
    col2 varchar UNIQUE,    
    col3 int
);

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

CREATE TABLE mytable2(  
    col1 varchar UNIQUE,
    col2 varchar UNIQUE,
    col3 int,
    CONSTRAINT ux_col1_col2 UNIQUE (col1,col2)
);

将处理您的上述查询:

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 CONSTRAINTux_col1_col2

但是等等,还有更多。。。

这个想法是保持一个计数器列是最新的,它在唯一列上匹配,或者如果两者都不存在,则插入零...

这条路和你现在走的不一样。“在任一唯一列上匹配”允许在两个或两个列上匹配。如果我理解你的意图,只需要一个标签,并增加适用记录上的计数器。所以:

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;
 类似资料:
  • 在表格中列出以下内容: 和 关于插入冲突,目前有: 我如何将unique_position和unique_position_sat_null纳入《关于冲突的约束》 尝试: 和 非常感谢。

  • 我的桌子有两个独特的列: 我想写保存或更新方法 My jooq code: 但我遇到了异常: “错误:没有唯一或排除约束匹配ON CONFLICT规范” 请帮助。

  • 我有一个Spring MVC应用程序,它使用Spring Data JPA作为我的JPA提供者来持久化Hibernate。我有一个数据库表,在列上有一个唯一的约束,因此为什么保存相应的实体可能会导致唯一的约束冲突。我想检测这是否发生在我的服务层中,以便我可以向用户呈现有意义的错误消息。以下是我的服务方法。 我的Spring Data JPA存储库看起来像这样: 现在,当发生唯一的约束冲突时,我得到

  • 我有一个用户创建屏幕,它记录了各种用户详细信息以及名字和手机号码。我有一个对应的用户表,其中名字和手机号码构成一个复合唯一键。此表中还定义了其他完整性约束。 当在创建用户屏幕上输入违反此约束的用户数据时,需要向用户显示“用户友好”错误消息。 当这种违反发生时,我从MySQL数据库中得到的异常是: 有两个选项可以显示有意义的消息(例如:“错误:给定手机号码的用户名已存在,请更改其中一个”)。 选项1

  • 我对Postgres Unique约束有问题,该约束包含多个可能包含空值的列。 让我们假设这种情况: Insert将插入('foo',bar')一次和('foo',NULL)两次(尽管直觉告诉它应该插入一次)。 在这种情况下,解决方案非常简单。我可以添加唯一的索引 但是当有更多的列和不同的类型(不仅仅是文本)时,问题就开始了。假设我们有10列,其中9列可以有值。也许我可以用大量的限制来解决它,但这

  • 我有两个表在postgres和。 用于创建表的Sql文件如下:https://nofile.io/f/Ef94rMFRh6C/file.sql 我想在每天结束时更新,条件如下: 如果已经不存在,那么从的记录需要插入到 如果存在,那么。 我使用下面的查询来更新歌曲摘要: 我得到以下错误: 错误:不存在与冲突规范匹配的唯一或排除约束