我必须将大量数据从文件转储到表 PostgreSQL。我知道它不支持 MySql 中的“忽略”“替换”等。网络上几乎所有与此相关的帖子都提出了相同的建议,例如将数据转储到临时表中,然后执行“插入...选择...在不存在的地方...”。
在文件数据本身包含重复主键的一种情况下,这将无济于事。任何人都知道如何在 PostgreSQL 中处理这个问题?
PS我是从一个java程序做的,如果它有帮助的话
我必须将大量数据从文件转储到表 PostgreSQL。我知道它不支持 MySql 中的“忽略”“替换”等。网络上几乎所有与此相关的帖子都提出了相同的建议,例如将数据转储到临时表中,然后执行“插入...选择...在不存在的地方...”。
在文件数据本身包含重复主键的一种情况下,这将无济于事。任何人都知道如何在 PostgreSQL 中处理这个问题?
PS我是从一个java程序做的,如果它有帮助的话
使用与您描述的相同的方法,但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
PostgreSQL 9.5 现在有upsert 功能。您可以按照 Igor 的说明进行操作,但最后的 INSERT 包含 ON CONFLICT DO NOTHING 子句。
INSERT INTO main_table
SELECT *
FROM tmp_table
ON CONFLICT DO NOTHING
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
丢弃所有其他行。
插入到按键分组的临时表中,这样您就可以摆脱重复项
如果不存在则插入