Подтвердить что ты не робот

Чтобы игнорировать дубликаты ключей во время 'copy from' в postgresql

Мне приходится сбрасывать большое количество данных из файла в таблицу PostgreSQL. Я знаю, что он не поддерживает "Игнорировать" "заменить" и т.д., Как это сделано в MySql. Почти все сообщения, касающиеся этого в Интернете, предложили то же самое, что и сброс данных в временную таблицу, а затем выполните "insert... select... where not exists...".

Это не поможет в одном случае, когда сами данные файла содержат повторяющиеся первичные ключи. У любого органа есть идея о том, как справиться с этим в PostgreSQL?

P.S. Я делаю это из java-программы, если это помогает

4b9b3361

Ответ 1

Используйте тот же самый подход, который вы описали, но DELETE (или группу или измените...) дублируйте PK в таблице temp перед загрузкой в ​​основную таблицу.

Что-то вроде:

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

Ответ 2

Ответ Igors мне очень помог, но я также столкнулся с проблемой, о которой упоминал Нейт в своем комментарии. Тогда у меня возникла проблема - возможно, помимо вопроса здесь, - что новые данные не только содержат дубликаты внутри, но и дублируют существующие данные. Что сработало для меня, было следующее.

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

PostgreSQL 9.5 теперь имеет функцию upsert. Вы можете следовать инструкциям Игоря, за исключением того, что окончательный INSERT включает предложение ON CONFLICT DO NOTING.

INSERT INTO main_table
SELECT *
FROM tmp_table
ON CONFLICT DO NOTHING

Ответ 4

Вставьте в таблицу temp, сгруппированную по ключу, чтобы избавиться от дубликатов

а затем вставьте, если не существует