使用SERIAL主键的INSERT或UPDATE表

时间:2017-01-18 00:09:21

标签: sql postgresql upsert

简单的问题,

如何在具有SERIAL(也称为自动增量)主键的PostgreSQL表中进行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图)。表是“友谊”,但UMLStar使用“public.Friendship”(如表名)导出奇怪的SQL。但这没关系,它适用于其他情况(我已成功注册/登录)。

Full schema 命令\ 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)

messenger =#\ 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';

2 个答案:

答案 0 :(得分:2)

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)

如果没有东西,你怎么会发生冲突?

答案 1 :(得分:0)

抱歉,如果我没有注意到问题的复杂性,但这似乎更简单:

ALTER TABLE public.friendship 
add column id serial;