postgres insert on conflict do nothing

最近写一个监控项目 吗,从es中获取数据有时候因为时间频率不准确导致数据出现重复,如果普通的insert 会导致其他非重复数据无法入库,这并不是我先要的效果,(重复数据跳过,正确的数据入库)为了避免此类情况,postgres提供了on confict 的语法,可以在批量插入的同时检查唯一性约束,

如果出现重复数据,那么action有两种,一种是do nothing  一种是DO UPDATE SET  可以根据需要是直接跳过还是更新新值。

 

[ 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 ]


相对于普通INSERT语法,覆盖写主要增加了ON CONFLICT子句,该子句分为两部分,分别是:

  • conflict_target,用于指定在哪些列上有冲突。conflict_target在conflict_action为DO NOTHING时可省略,在conflict_action为DO UPDATE时,需要指定一个列表,指定主键列的列表或Unique Index列的列表
  • conflict_action,用于指定冲突后需要执行的动作。分为DO NOTHING和DO UPDATE两种。 (1)DO NOTHING表示如果有冲突,则丢弃待插入的数据。 (2)DO UPDATE表示如果有冲突,则按照后面的UPDATE语法进行数据覆盖。

在DO UPDATE SET子句中,可以使用EXCLUDED来表示冲突的数据构成的伪表,引用其中的列。比如表tbl有一主键列pri_key,有一列非主键列col_name,要在有冲突的情况下,使用插入的col_name值覆盖掉原来的col_name的值,则可以写成:

insert into tbl values (0, 1), (2, 3), (4, 5)
on conflict (pri_key) do update set tbl.col_name = excluded.col_name;
	
posted on 2022-12-01 02:46  Shawn_1026  阅读(895)  评论(0编辑  收藏  举报