首页 > 解决方案 > 发生冲突时如何使用新值进行更新

问题描述

create table new(id serial pk ,name varchar (10),age int)

id是自动生成的。

insert into new (id,name,age)values(1,' xyz ',21)on conflict(id) do update set name=new_name,age=new_age

id它已经可用时,它应该update使用主键 id 按新值排列。当我第一次插入数据时,我没有通过,id因为它的串行类型会自动生成。在这种情况下,我可以发送idnull因为当我尝试更新该时间id字段时是必需的。

标签: stored-procedurespostgresql-9.5stored-functions

解决方案


从问题中可以清楚地看出,您提供的代码不是您拥有的确切代码。正如您所描述的,由于您在没有被传递的情况下插入id,因此您的实际代码大概如下所示:

insert into yourtable(name, age)
values(' xyz ', 21)
on conflict(id) do
update set name='new_name',age='new_age';

由于您没有通过a ,因此id您将永远不会有 a conflict,因此将插入所有内容。为了处理conflict,您需要了解id并执行以下操作:

insert into yourtable(id, name, age)
values(1, ' xyz ', 21)
on conflict(id) do
update set name='new_name',age='new_age';

很明显,你不一定知道记录的 id 是什么,但这是一个算法问题。您将需要找出它是什么id

请看https://www.postgresqltutorial.com/postgresql-upsert/

它有一个例子:

INSERT INTO customers (name, email)
VALUES('Microsoft','hotline@microsoft.com') 
ON CONFLICT (name) 
DO 
   UPDATE SET email = EXCLUDED.email || ';' || customers.email;

该表定义为

DROP TABLE IF EXISTS customers;

CREATE TABLE customers (
    customer_id serial PRIMARY KEY,
    name VARCHAR UNIQUE,
    email VARCHAR NOT NULL,
    active bool NOT NULL DEFAULT TRUE
);

请注意,name因此unique,如果insert尝试添加name已存在的记录,则命令包含在conflict该记录中并且将被更新。如果您不提供id,那么您的命令将不会有任何冲突,并且不会更新,而是insert所有记录。


推荐阅读