使用 SERIAL 主键插入或更新表

INSERT or UPDATE tables with SERIAL primary key

简单的问题,

我如何在具有 SERIAL(也称为自动递增)主键的 PostgreSQL table 中进行 UPSERT?

我找不到真正可信的来源,这就是我在这里问的原因。

这是我目前得到的,但它不起作用。

INSERT INTO public.friendship (Username_1, Username_2, Status) 
VALUES ("User1", "User2", "Accepted") 
ON CONFLICT (Username_1, Username_2) 
DO UPDATE SET (Status) = ("Accepted")   
WHERE Username_1 = "User1" AND Username_2 = "User2";

完整架构(ER 图)。 Table 是 "Friendship" 但 UMLStar 导出奇怪的 SQL 与 "public.Friendship" 类似 table 名称。但这没关系,它适用于其他情况(我 Register/Login 工作成功)。

命令 \d,关系列表

 Schema |              Name               |   Type   |  Owner
--------+---------------------------------+----------+----------
 public | activitydata                    | table    | postgres
 public | activitydata_activitydataid_seq | sequence | postgres
 public | chatroom                        | table    | postgres
 public | chatroom_chatroomid_seq         | sequence | postgres
 public | country                         | table    | postgres
 public | friendship                      | table    | postgres
 public | friendship_friendshipid_seq     | sequence | postgres
 public | message                         | table    | postgres
 public | message_messageid_seq           | sequence | postgres
 public | participates                    | table    | postgres
 public | participates_participatesid_seq | sequence | postgres
 public | user                            | table    | postgres
(12 rows)

信使=#\d友谊

Table "public.friendship"
    Column    |  Type   |                             Modifiers
--------------+---------+-------------------------------------------------------------------
 friendshipid | integer | not null default nextval('friendship_friendshipid_seq'::regclass)
 username_1   | text    | not null
 username_2   | text    | not null
 status       | text    | not null
Indexes:
    "friendship_pkey" PRIMARY KEY, btree (friendshipid)
    "friendship_username_1_idx" btree (username_1)
    "friendship_username_2_idx" btree (username_2)

执行的命令:

messenger=# INSERT INTO public.friendship (Username_1, Username_2, Status)
messenger-# VALUES ('User1', 'User2', 'Accepted')
messenger-#  ON CONFLICT (Username_1, Username_2)
messenger-#  DO UPDATE SET (Status) = ('Accepted')
messenger-#  WHERE Username_1 = 'User1' AND Username_2 = 'User2';
ERROR:  column reference "username_1" is ambiguous
LINE 5:  WHERE Username_1 = 'User1' AND Username_2 = 'User2';
Table "public.friendship"
    Column    |  Type   |                             Modifiers
--------------+---------+-------------------------------------------------------------------
 friendshipid | integer | not null default nextval('friendship_friendshipid_seq'::regclass)
 username_1   | text    | not null
 username_2   | text    | not null
 status       | text    | not null
Indexes:
    "friendship_pkey" PRIMARY KEY, btree (friendshipid)
    "friendship_username_1_idx" btree (username_1)
    "friendship_username_2_idx" btree (username_2)

这没有在 (username_1, username_2)

上显示唯一键

你应该做的是

BEGIN;
  DROP INDEX friendship_username_1_idx,
  CREATE UNIQUE INDEX ON foo(username_1, username_2);
COMMIT;

如果您从不查询 username_2 而不查询 username_1 那么您应该放弃 friendship_username_2_idx 并让一个复合 UNIQUE 索引为您工作。

我们想要 \d Friendship 作为参考,因为如果您有唯一索引,它会显示...

      Table "public.foo"
 Column |  Type   | Modifiers 
--------+---------+-----------
 a      | integer | 
 b      | integer | 
Indexes:
    "foo_a_b_idx" UNIQUE, btree (a, b)

什么都没有,怎么会冲突?

抱歉,如果我错过了问题的复杂性,但这看起来更简单:

ALTER TABLE public.friendship 
add column id serial;