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

Kam*_*Kam 50 sql postgresql

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

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

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

Igo*_*nko 64

使用与您描述的方法相同的方法,但在加载到主表之前,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)
Run Code Online (Sandbox Code Playgroud)

详细说明:CREATE TABLE AS,COPY,DISTINCT ON

  • 调整:在更现代的PSQL上使用upsert,例如INSERT语句的"ON CONFLICT DO NOTHING". (5认同)
  • 当我尝试复制命令时,我得到错误:关系"tmp_table"不存在 (4认同)
  • 将答案的代码与事务一起包装(“开始; ...;提交;”),以便“ on commit drop”将在事务结束时删除临时表。否则,该表将立即删除,就在“复制”和“插入”有机会运行之前。因此“ tmp_table不存在”。 (2认同)

小智 38

PostgreSQL 9.5现在具有upsert功能.您可以按照Igor的说明进行操作,但最终的INSERT包括"冲突没有"这一条款.

INSERT INTO main_table
SELECT *
FROM tmp_table
ON CONFLICT DO NOTHING
Run Code Online (Sandbox Code Playgroud)


Den*_*her 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
Run Code Online (Sandbox Code Playgroud)

内部和外部重复项在内部和外部重复相同tmp_table,然后DISTINCT ON (email)部分删除它们.将ORDER BY可确保该行是第一位的结果集,并DISTINCT随后丢弃所有进一步行.