Postgresql批量插入或忽略

我有责任将代码sqlite切换到postgres.我遇到问题的其中一个查询将在下面复制.
INSERT INTO group_phones(group_id,phone_name)
SELECT g.id,p.name 
FROM phones AS p,groups as g
WHERE g.id IN ($add_groups) AND p.name IN ($phones);

当存在重复记录时会出现问题.在此表中,两个值的组合必须是唯一的.我在其他地方使用了一些plpgsql函数来执行更新或插入操作,但在这种情况下,我可以一次执行多个插入操作.我不知道如何为此编写存储例程.感谢所有sql专家的帮助!

有3个挑战.

>您的查询在表格电话和组之间没有JOIN条件,这实际上是有限的CROSS JOIN – 您最有可能不打算这样做.即每个符合条件的手机都会与符合条件的每个组合在一起.如果您有100个手机和100个组已经有10,000个组合.
>插入(group_id,phone_name)的不同组合
>避免插入表group_phones中已存在的行.

所有事情都认为它看起来像这样:

INSERT INTO group_phones(group_id,phone_name)
SELECT i.id,i.name
FROM  (
    SELECT disTINCT g.id,p.name -- get distinct combinations
    FROM   phones p
    JOIN   groups g ON ??how are p & g connected??
    WHERE  g.id IN ($add_groups)
    AND    p.name IN ($phones)
    ) i
LEFT JOIN group_phones gp ON (gp.group_id,gp.phone_name) = (i.id,i.name)
WHERE gp.group_id IS NULL  -- avoid duping existing rows

并发

此表单最大限度地减少了并发写入操作的竞争条件的可能性.如果你的表有很大的并发写入负载,你可能想要lock the table exclusively或使用serializable transaction isolation,这可以防止极端不可能的情况,即在约束验证之间的微小时隙中并发事务改变行(行不存在)以及查询中的写操作.

BEGIN ISOLATION LEVEL SERIALIZABLE;
INSERT ...
COMMIT;

如果回滚时出现序列化错误,请准备重复该事务.
有关该主题的更多信息,可以从blog post by @depeszrelated question on SO开始.

但是,通常情况下,您甚至无需担心任何此类问题.

性能

LEFT JOIN tbl ON right_col = left_col WHERE right_col IS NULL

通常是右表中具有不同列的最快方法.如果你在列中有欺骗(特别是如果有很多),

WHERE NOT EXISTS (SELECT 1 FROM tbl WHERE right_col = left_col)

可能会更快,因为它可以在找到第一行后立即停止扫描.

您也可以使用IN,就像@dezso演示一样,但它在Postgresql中通常较慢.

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...