В PostgreSQL я выполняю UPSERT на 1000 строк, я использую ON CONFLICT ... НИЧЕГО, если 1 строка не работает, вставляются ли другие 999? - PullRequest
1 голос
/ 15 января 2020

Я пытаюсь понять, как работает предложение ON CONFLICT. Я хочу, чтобы в случае сбоя вставки по какой-либо причине я хотел, чтобы он ничего не делал со строкой, но продолжаю обрабатывать другие элементы в массовой вставке.

Вот мой сценарий. Я строю запрос массовой вставки, с 1000 строк для вставки. В настоящее время мой запрос имеет:

INSERT INTO table (...,...,...) 
VALUES (...,...,...),(...,null..,...), (998 more) 
ON CONFLICT ON CONSTRAINT primary_key DO NOTHING

Что я хочу знать, могу ли я сделать это:

INSERT INTO table (...,...,...) VALUES (...,...,...),(...,null..,...), (998 more) 
ON CONFLICT DO NOTHING

Это будет эффективно принимать любой конфликт при вставке строки (в моем случае ноль ограничение на столбец) и просто не вставлять его. Мне нужно убедиться, что при наличии 1 конфликта для одной строки все остальные 999 строк все равно будут вставлены.

ОБНОВЛЕНИЕ: вот демонстрация, показывающая проблему, с которой я столкнулся: https://dbfiddle.uk/?rdbms=postgres_9.5&fiddle=8947dbcd38e9136531b907d3c745c0f5

ОБНОВЛЕНИЕ 2: Похоже, что при передаче нулевых значений происходит сбой всего процесса массовой вставки.

FINAL ОБНОВЛЕНИЕ: Принял первый ответ из-за этой классной демонстрационной ссылки - которая помогла мне понять (и в комментариях), что null не захвачено, поэтому мне просто нужно изменить структуру таблицы и полагаться на первичный ключ ... поэтому при добавлении повторяющихся нулей ограничение pkey срабатывает. Спасибо всем!

1 Ответ

3 голосов
/ 15 января 2020

Будут вставлены все строки, для которых нет конфликта, и конфликтующая строка будет проигнорирована.

Рассмотрим это демо :

-- create the table and insert a record with id 1
create table t (id int primary key, info text);
insert into t values (1, 'old');
-- 1 rows affected

-- attempt to insert 5 'new' records with ids 1 .. 5
insert into t 
select n, 'new' from generate_series(1, 5) as n(n) on conflict do nothing;
-- 4 rows affected

-- check the results
select * from t;
id | info
-: | :---
 1 | old 
 2 | new 
 3 | new 
 4 | new 
 5 | new 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...