暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用 INSERT ON CONFLICT 更新插入数据

原创 ByteHouse 2025-05-08
496

摘要:

在 PostgreSQL中,如何使用INSERT ON CONFLICT语法覆盖写入数据?
针对数据写入时有主键冲突的情况,INSERT ON CONFLICT语法可以将冲突主键的INSERT行为转换为UPDATE行为,从而实现冲突主键的覆盖写入。该特性又称UPSERT覆盖写,与MySQL的REPLACE INTO类似。

Postgresql insert on conflict

ON CONFLICT子句可以实现覆盖写入。该子句由conflict_target和conflict_action组成。

参数 说明
conflict_target conflict_action取值为Do Update时,conflict_target需要指定用来定义冲突的主键列或唯一索引列。conflick_action取值为Do Nothing时,conflict_target可省略。
conflict_action 用于指定冲突后需要执行的动作。取值说明:DO NOTHING:如果conflict_target指定的列有冲突,则丢弃待插入的数据。DO UPDATE:如果conflict_target指定的列有冲突,则按照后面的UPDATE子句进行数据覆盖。

创建测试表

CREATE TABLE user_info (
    "name" varchar(255),
    "age" int4,
    "sex" varchar(255),
    "inserttime" date,
    constarint "user_info_pk" primary key ("name")

)

新增测试数据

insert into user_info name, age, sex,inserttime) values('jruing','男',27,'2023-05-10 00:00:00') 

insert 新增时忽略已存在的数据

insert into user_info(name, age, sex,inserttime) values('jruing',27,'男','2023-05-10 00:00:02') on conflict(name) do nothing

insert 有则更新,无则插入

insert into table_name(name, age, sex, inserttime) values ('jruing',27,'男','2023-05-10 00:00:02') on conflict(name) do update set inserttime=EXCLUDED.inserttime

confilct中包含的字段必须为冲突的列名(冲突是指违反主键约束,唯一约束等其他约束)

mysql INSERT-ON-CONFLICT

实现 “mysql INSERT-ON-CONFLICT” 的步骤

创建数据表

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(50)
);

插入数据

INSERT INTO users (id, name)
VALUES (1, 'John'), (2, 'Jane'), (3, 'Mike');

实现 INSERT-ON-CONFLICT
当我们插入数据时,可能会出现冲突,例如,当我们尝试插入一个已经存在的记录时。为了解决这个问题,MySQL 提供了 INSERT-ON-CONFLICT 语法。

INSERT INTO users (id, name)
VALUES (4, 'Bob')
ON DUPLICATE KEY UPDATE name = VALUES(name);

插入一个 id 为 4,name 为 ‘Bob’ 的记录。如果这条记录已经存在,那么 name 字段将被更新为 ‘Bob’。

Oracle merge 与 PG新特性 UPSERT

PostgreSQL 9.5于2016年1月7日正式发布,其中包含新特性“UPSERT”(INSERT, ON CONFLICT UPDATE), 插入数据,正常时写入,主键冲突时更新。

在进行SQL语句编写时,我们经常会遇到大量的同时进行Insert/Update的语句 ,也就是说当存在记录时,就更新(Update),不存在数据时,就插入(Insert)。

MERGE INTO 是ORACLE数据库 SQL 中的一种数据操作语句,它结合了 INSERT、UPDATE 和 DELETE 操作的功能,通常被称为"upsert"操作(update + insert)。

在Oracle数据库的使用中,向表中插入数据时,如果待插入的记录表中已经存在,就用新记录的值更新原记录;如果不存在,就插入新记录。这时候,就需要用merge语句。

MERGE INTO employees t
USING new_employees s
ON (t.employee_id = s.employee_id)
WHEN MATCHED THEN
    UPDATE SET t.salary = s.salary, t.department = s.department
WHEN NOT MATCHED THEN
    INSERT (employee_id, name, salary, department)
    VALUES (s.employee_id, s.name, s.salary, s.department);

这个语句会将new_employees表中的数据合并到employees表中,如果employee_id已存在则更新薪资和部门,如果不存在则插入新记录。

update采用的类似nested loop的方式,对更新的每一行,都会对查询的表扫描一次;merge into这里选择的是hash join,则针对每张表都是做了一次 full table scan,对每张表都只是扫描一次。

Oracle官方建议
This statement is a convenient way to combine multiple operations. It lets you avoid multiple INSERT, UPDATE, and DELETE DML statements.
merge方法是最简洁,效率最高的方式,在大数据量更新时优先使用这种方式。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论