Postgresql insert on conflict笔记
Posted Jruing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Postgresql insert on conflict笔记相关的知识,希望对你有一定的参考价值。
描述
针对数据写入时有主键冲突的情况,INSERT ON CONFLICT语法可以将冲突主键的INSERT行为转换为UPDATE行为,从而实现冲突主键的覆盖写入。该特性又称UPSERT覆盖写,与MySQL的REPLACE INTO类似。
[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
DEFAULT VALUES | VALUES ( expression | DEFAULT [, ...] ) [, ...] | query
[ ON CONFLICT [ conflict_target ] conflict_action ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
其中,conflict_target为:
( index_column_name | ( index_expression ) [ COLLATE collation ] [ opclass ] [, ...] )
其中,conflict_action为:
DO NOTHING
DO UPDATE SET column_name = expression | DEFAULT |
( column_name [, ...] ) = ( expression | DEFAULT [, ...] )
[, ...]
[ WHERE condition ]
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 jruing.user_info (
"name" varchar(255),
"age" int4,
"sex" varchar(255),
"inserttime" date,
constarint "user_info_pk" primary key ("name")
)
新增测试数据
insert into table_name(name, age, sex,inserttime) values(\'jruing\',\'男\',27,\'2023-05-10 00:00:00\')
insert 新增时忽略已存在的数据
insert into table_name(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中包含的字段必须为冲突的列名(冲突是指违反主键约束,唯一约束等其他约束)
本文来自博客园,作者:Jruing,转载请注明原文链接:https://www.cnblogs.com/jruing/p/17387971.html
如何在 PostgreSQL 9.5 中执行 INSERT INTO SELECT 和 ON DUPLICATE UPDATE?
【中文标题】如何在 PostgreSQL 9.5 中执行 INSERT INTO SELECT 和 ON DUPLICATE UPDATE?【英文标题】:How to do INSERT INTO SELECT and ON DUPLICATE UPDATE in PostgreSQL 9.5? 【发布时间】:2017-02-01 11:05:36 【问题描述】:我正在尝试在 PostgreSQL 中执行以下操作
INSERT INTO blog_sums ( blog_id, date, total_comments)
SELECT blog_id, '2016-09-22', count(comment_id) as total_comments_update
FROM blog_comments
WHERE date = '2016-09-22'
GROUP BY blog_id
ON CONFLICT (blog_id ,date)
DO UPDATE SET blog_sums.total_comments = total_comments_update;
我在 date + blog_id 上有唯一键,但我不断收到错误消息:
错误:列“total_cmets_update”不存在
我正在寻找在这种情况下更新重复/冲突的“正确”方式和最有效的方式
我的桌子是
blog_comments (blog_id, comment_id, comment, date)
blog_sums ( blog_id, date, total_comments) . unique on blog_id+date
谢谢
【问题讨论】:
【参考方案1】:您不能从DO UPDATE SET
子句中的选择访问列别名。您可以使用 excluded
表别名,其中包括由于冲突而无法插入的所有行:
INSERT INTO blog_sums ( blog_id, date, total_comments)
SELECT blog_id, '2016-09-22', count(comment_id) as total_comments_update
FROM blog_comments
WHERE date = '2016-09-22'
GROUP BY blog_id
ON CONFLICT (blog_id ,date)
DO UPDATE SET total_comments = excluded.total_comments;
所以最后一行中的excluded.total_comments
指的是我们尝试插入但由于冲突而无法插入的total_comments
的值。
【讨论】:
不要忘记 GROUP BY 否则你会得到(使用 postgresql 9.6.1):错误:ON CONFLICT DO UPDATE 命令不能再次影响行提示:确保没有建议插入的行在同一命令中具有重复的约束值。以上是关于Postgresql insert on conflict笔记的主要内容,如果未能解决你的问题,请参考以下文章
Postgresql EXCLUDE 约束在 INSERT 时未触发 ON CONFLICT
如何在 flask_sqlalchemy 中使用 PostgreSQL 的“INSERT...ON CONFLICT”(UPSERT)功能?