如何模拟与PostgreSQL的“插入忽略”和“重复键更新”(SQL合并)?如何模拟与Postgre

2019-05-13 11:33发布

一些SQL服务器具有其中一个功能INSERT是否会违反主/唯一键约束被跳过。 举例来说,MySQL已经INSERT IGNORE

什么是模仿的最好办法INSERT IGNOREON DUPLICATE KEY UPDATE PostgreSQL的?

Answer 1:

试着做一个更新。 如果不修改,这意味着它不存在任何行,所以做一个插件。 显然,你在一个事务中做到这一点。

当然,你可以在一个函数把这个包,如果你不想把多余的代码在客户端。 您还需要在思维非常罕见的比赛条件的循环。

有这样的文档中的例子: http://www.postgresql.org/docs/9.3/static/plpgsql-control-structures.html ,例如40-2右侧底部。

这通常是最简单的方法。 你可以做一些神奇的规则,但它可能会是一个很大混乱。 我建议的总结在功能上是途径的任何一天。

这适用于单排或几排,价值观。 如果你有大量的行例如从处理的子查询,你最好拆分为两个查询,一个用于INSERT和一个用于更新的(如适当的加入当然/子选择 - 没有必要写你的主过滤两次)



Answer 2:

在PostgreSQL 9.5,这是目前本机功能 (如MySQL已经有好几年了):

INSERT ... ON冲突束手无策/ UPDATE( “UPSERT”)

9.5带来了“UPSERT”操作的支持。 INSERT延伸到接受ON CONFLICT DO UPDATE / IGNORE子句。 本节规定的替代行动采取一个想成为重复违规的事件。

...

新语法的又一范例:

INSERT INTO user_logins (username, logins)
VALUES ('Naomi',1),('James',1) 
ON CONFLICT (username)
DO UPDATE SET logins = user_logins.logins + EXCLUDED.logins;


Answer 3:

编辑:如果你错过了沃伦的回答 ,PG9.5现在有这个本身; 及时升级!


建立在比尔Karwin的回答,拼出一个基于规则的方法是什么样子(来自同一DB另一个模式转移,并用多列主键):

CREATE RULE "my_table_on_duplicate_ignore" AS ON INSERT TO "my_table"
  WHERE EXISTS(SELECT 1 FROM my_table 
                WHERE (pk_col_1, pk_col_2)=(NEW.pk_col_1, NEW.pk_col_2))
  DO INSTEAD NOTHING;
INSERT INTO my_table SELECT * FROM another_schema.my_table WHERE some_cond;
DROP RULE "my_table_on_duplicate_ignore" ON "my_table";

注:该规则适用于所有的INSERT操作,直到规则被丢弃,所以不太专案。



Answer 4:

为了让插入无视逻辑,你可以这样做以下。 我发现简单地从字面值的select语句插入效果最好,那么你就可以屏蔽掉重复键用NOT EXISTS子句。 要获得重复的逻辑更新我怀疑一个PL / pgSQL的循环将是必要的。

INSERT INTO manager.vin_manufacturer
(SELECT * FROM( VALUES
  ('935',' Citroën Brazil','Citroën'),
  ('ABC', 'Toyota', 'Toyota'),
  ('ZOM',' OM','OM')
  ) as tmp (vin_manufacturer_id, manufacturer_desc, make_desc)
  WHERE NOT EXISTS (
    --ignore anything that has already been inserted
    SELECT 1 FROM manager.vin_manufacturer m where m.vin_manufacturer_id = tmp.vin_manufacturer_id)
)


Answer 5:

对于那些你有Postgres的9.5或更高版本,新的ON CONFLICT无能为力语法应工作:

INSERT INTO target_table (field_one, field_two, field_three ) 
SELECT field_one, field_two, field_three
FROM source_table
ON CONFLICT (field_one) DO NOTHING;

对于我们这些谁拥有的早期版本,这一权利将联接工作,而不是:

INSERT INTO target_table (field_one, field_two, field_three )
SELECT source_table.field_one, source_table.field_two, source_table.field_three
FROM source_table 
LEFT JOIN target_table ON source_table.field_one = target_table.field_one
WHERE target_table.field_one IS NULL;


Answer 6:

INSERT INTO mytable(col1,col2) 
    SELECT 'val1','val2' 
    WHERE NOT EXISTS (SELECT 1 FROM mytable WHERE col1='val1')


Answer 7:

看起来像PostgreSQL支持所谓的规则架构对象。

http://www.postgresql.org/docs/current/static/rules-update.html

你可以创建一个规则ON INSERT给定表,使其做NOTHING如果行具有给定主键值存在,否则使它做一个UPDATE的,而不是INSERT如果行具有给定主键值存在。

我还没有尝试过这个自己,所以我不能从经验发言或提供一个例子。



Answer 8:

作为@hanmari在他的评论中提到。 插入一个Postgres表时,在冲突(..)什么也不做就是用不插入重复数据最好的代码:

query = "INSERT INTO db_table_name(column_name)
         VALUES(%s) ON CONFLICT (column_name) DO NOTHING;"

代码的ON CONFLICT线将允许插入语句仍然插入数据行。 查询和值的代码是从Excel中插入日期到一个postgres分贝表的一个例子。 我已经加入到一个Postgres表我用,以确保ID字段是唯一约束。 不是运行于数据行是相同的,我添加一行SQL代码重新编号的ID列从1开始的一个实施例的删除:

q = 'ALTER id_column serial RESTART WITH 1'

如果我的数据有一个ID字段,我不会用这个作为主要的ID /序列号,我创建了一个ID列,我将它设置为串口。 我希望这个信息是对大家有所帮助。 *我在软件开发/编码没有大学学位。 我知道的一切在编码,我对我自己的学习。



Answer 9:

该解决方案避免了使用规则:

BEGIN
   INSERT INTO tableA (unique_column,c2,c3) VALUES (1,2,3);
EXCEPTION 
   WHEN unique_violation THEN
     UPDATE tableA SET c2 = 2, c3 = 3 WHERE unique_column = 1;
END;

但它有一个缺点表现(见PostgreSQL.org ):

将一种含有一种例外条款块是显著更昂贵比块没有一个进入和退出。 因此,不要无需使用异常。



Answer 10:

在批量,你可以随时插入之前删除行。 一排的缺失不存在不会导致错误,因此它的安全跳过。



Answer 11:

对于数据导入脚本,以取代“IF NOT EXISTS”,在某种程度上,有一个略显尴尬的制剂,其仍然工作:

DO
$do$
BEGIN
PERFORM id
FROM whatever_table;

IF NOT FOUND THEN
-- INSERT stuff
END IF;
END
$do$;


文章来源: how to emulate “insert ignore” and “on duplicate key update” (sql merge) with postgresql?