在postgresql中'copy from'期间忽略重复键

时间:2012-12-19 07:17:47

标签: sql postgresql

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

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

P.S。我正在从java程序中执行此操作,如果它有帮助

4 个答案:

答案 0 :(得分:55)

使用与您描述的方法相同的方法,但在加载到主表之前,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 ASCOPYDISTINCT ON

答案 1 :(得分:28)

PostgreSQL 9.5现在有upsert functionality。您可以按照Igor的说明进行操作,但最终的INSERT包含“冲突没有”的条款。

INSERT INTO main_table
SELECT *
FROM tmp_table
ON CONFLICT DO NOTHING

答案 2 :(得分:11)

伊戈尔的答案帮助了我很多,但我也遇到了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然后丢弃所有其他行。

答案 3 :(得分:0)

插入按键分组的临时表,以便删除重复项

然后插入(如果不存在)