【问题标题】:Postgres on conflict do update on composite primary keys冲突中的 Postgres 确实更新了复合主键
【发布时间】:2018-12-24 19:19:07
【问题描述】:

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

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) 
);

【问题讨论】:

  • 您是否尝试过 ON CONFLICT ON CONSTRAINT 变体?

标签: sql postgresql upsert


【解决方案1】:

只需将两个键都放在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)

演示:db<>fiddle

【讨论】:

  • 我试过这个。目前正在对所有情况进行测试。由于文档说您需要唯一的列,因此我不确定此方法是否涵盖所有情况。测试完所有案例后会回复您。
  • @pewpewlasers 我相信,在这种情况下,复合 pk 被视为单个元素,因此是唯一值。请让我知道在哪些情况下它可能不起作用。
【解决方案2】:

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

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;

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

【讨论】:

    猜你喜欢
    • 2019-02-14
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多