关于冲突的Postgres会对复合主键进行更新

问题描述 投票:3回答:2

我有一个表,用户可以回答问题。规则是用户可以回答许多问题,或者许多用户可以回答一个问题,但用户只能回答一次特定问题。如果用户再次回答问题,则应该简单地替换旧问题。通常,当我们处理唯一列时,冲突更新会起作用。在这种情况下,列person_idquestion_id不能是唯一的。然而,两者的结合总是独一无二的。如何实现在冲突时更新的insert语句?

CREATE TABLE "answer" (
  "person_id" integer NOT NULL REFERENCES person(id), 
  "question_id" integer NOT NULL REFERENCES question(id) ON DELETE CASCADE, /* INDEXED */
  "answer" character varying (1200) NULL,
  PRIMARY KEY (person_id, question_id) 
);
sql postgresql upsert
2个回答
9
投票

只需将两个键放在ON CONFLICT子句中:

INSERT INTO answer VALUES (1,1,'q1') 
ON CONFLICT (person_id,question_id) 
DO UPDATE SET answer = EXCLUDED.answer; 

例:

INSERT INTO answer VALUES (1,1,'q1') 
ON CONFLICT (person_id,question_id) 
DO UPDATE SET answer = EXCLUDED.answer;             

SELECT * FROM answer;
 person_id | question_id | answer 
-----------+-------------+--------
         1 |           1 | q1
(1 Zeile)

INSERT INTO answer VALUES (1,1,'q1-UPDATED') 
ON CONFLICT (person_id,question_id) 
DO UPDATE SET answer = EXCLUDED.answer;             

SELECT * FROM answer;
 person_id | question_id |   answer   
-----------+-------------+------------
         1 |           1 | q1-UPDATED
(1 Zeile)

3
投票

您还可以在表外部定义主数据库,然后您不需要重写其中包含的所有列。

CREATE TABLE "answer" (
  "person_id" integer NOT NULL REFERENCES person(id), 
  "question_id" integer NOT NULL REFERENCES question(id) ON DELETE CASCADE, /* INDEXED */
  "answer" character varying (1200) NULL);

ALTER TABLE "answer" ADD CONSTRAINT answer_pk PRIMARY KEY (person_id, question_id);

然后:

INSERT INTO answer VALUES (1,1,'q1') ON CONFLICT ON CONSTRAINT answer_pk DO UPDATE SET answer = EXCLUDED.answer;

当约束在将来发生变化时,您无需手动调整insert语句来反映这一点。

© www.soinside.com 2019 - 2024. All rights reserved.