71

我必须将大量数据从文件转储到表 PostgreSQL。我知道它不支持 MySql 中的“忽略”“替换”等。网络上几乎所有与此相关的帖子都提出了相同的建议,例如将数据转储到临时表中,然后执行“插入...选择...在不存在的地方...”。

在文件数据本身包含重复主键的一种情况下,这将无济于事。任何人都知道如何在 PostgreSQL 中处理这个问题?

PS我是从一个java程序做的,如果它有帮助的话

4

4 回答 4

94

使用与您描述的相同的方法,但DELETE(或分组,或修改......)PK在加载到主表之前在临时表中重复。

就像是:

CREATE TEMP TABLE tmp_table 
ON COMMIT DROP
AS
SELECT * 
FROM main_table
WITH NO DATA;

COPY tmp_table FROM 'full/file/name/here';

INSERT INTO main_table
SELECT DISTINCT ON (PK_field) *
FROM tmp_table
ORDER BY (some_fields)

详细信息:CREATE TABLE AS, COPY,DISTINCT ON

于 2012-12-19T09:54:13.437 回答
55

PostgreSQL 9.5 现在有upsert 功能。您可以按照 Igor 的说明进行操作,但最后的 INSERT 包含 ON CONFLICT DO NOTHING 子句。

INSERT INTO main_table
SELECT *
FROM tmp_table
ON CONFLICT DO NOTHING
于 2016-09-28T14:39:39.870 回答
16

Igor 的回答对我帮助很大,但我也遇到了 Nate 在他的评论中提到的问题。然后我遇到了一个问题——也许除了这里的问题——新数据不仅在内部包含重复,而且还与现有数据重复。对我有用的是以下内容。

CREATE TEMP TABLE tmp_table AS SELECT * FROM newsletter_subscribers;
COPY tmp_table (name, email) FROM stdin DELIMITER ' ' CSV;
SELECT count(*) FROM tmp_table;  -- Just to be sure
TRUNCATE newsletter_subscribers;
INSERT INTO newsletter_subscribers
    SELECT DISTINCT ON (email) * FROM tmp_table
    ORDER BY email, subscription_status;
SELECT count(*) FROM newsletter_subscribers;  -- Paranoid again

内部和外部副本在 中变得相同,tmp_table然后DISTINCT ON (email)部件将其删除。ORDER BY确保所需的行首先出现在结果集中,然后DISTINCT丢弃所有其他行。

于 2014-12-28T16:35:18.163 回答
0

插入到按键分组的临时表中,这样您就可以摆脱重复项

如果不存在则插入

于 2012-12-19T07:29:37.420 回答