一些SQL服务器具有其中一个功能INSERT
是否会违反主/唯一键约束被跳过。 举例来说,MySQL已经INSERT IGNORE
。
什么是模仿的最好办法INSERT IGNORE
和ON DUPLICATE KEY UPDATE
PostgreSQL的?
一些SQL服务器具有其中一个功能INSERT
是否会违反主/唯一键约束被跳过。 举例来说,MySQL已经INSERT IGNORE
。
什么是模仿的最好办法INSERT IGNORE
和ON DUPLICATE KEY UPDATE
PostgreSQL的?
试着做一个更新。 如果不修改,这意味着它不存在任何行,所以做一个插件。 显然,你在一个事务中做到这一点。
当然,你可以在一个函数把这个包,如果你不想把多余的代码在客户端。 您还需要在思维非常罕见的比赛条件的循环。
有这样的文档中的例子: http://www.postgresql.org/docs/9.3/static/plpgsql-control-structures.html ,例如40-2右侧底部。
这通常是最简单的方法。 你可以做一些神奇的规则,但它可能会是一个很大混乱。 我建议的总结在功能上是途径的任何一天。
这适用于单排或几排,价值观。 如果你有大量的行例如从处理的子查询,你最好拆分为两个查询,一个用于INSERT和一个用于更新的(如适当的加入当然/子选择 - 没有必要写你的主过滤两次)
在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;
编辑:如果你错过了沃伦的回答 ,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
操作,直到规则被丢弃,所以不太专案。
为了让插入无视逻辑,你可以这样做以下。 我发现简单地从字面值的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)
)
对于那些你有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;
INSERT INTO mytable(col1,col2)
SELECT 'val1','val2'
WHERE NOT EXISTS (SELECT 1 FROM mytable WHERE col1='val1')
看起来像PostgreSQL支持所谓的规则架构对象。
http://www.postgresql.org/docs/current/static/rules-update.html
你可以创建一个规则ON INSERT
给定表,使其做NOTHING
如果行具有给定主键值存在,否则使它做一个UPDATE
的,而不是INSERT
如果行具有给定主键值存在。
我还没有尝试过这个自己,所以我不能从经验发言或提供一个例子。
作为@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列,我将它设置为串口。 我希望这个信息是对大家有所帮助。 *我在软件开发/编码没有大学学位。 我知道的一切在编码,我对我自己的学习。
该解决方案避免了使用规则:
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 ):
将一种含有一种例外条款块是显著更昂贵比块没有一个进入和退出。 因此,不要无需使用异常。
在批量,你可以随时插入之前删除行。 一排的缺失不存在不会导致错误,因此它的安全跳过。
对于数据导入脚本,以取代“IF NOT EXISTS”,在某种程度上,有一个略显尴尬的制剂,其仍然工作:
DO
$do$
BEGIN
PERFORM id
FROM whatever_table;
IF NOT FOUND THEN
-- INSERT stuff
END IF;
END
$do$;