INSERT
просто ще вмъкне всички редове и нищо ще се случи специално,освен ако имате някакъв вид ограничение забраняване на дублиращи се/припокриващи се стойности (PRIMARY KEY
, UNIQUE
, CHECK
или EXCLUDE
ограничение) - което не споменахте във вашия въпрос. Но това вероятно ви тревожи.
Приемайки UNIQUE
или PK ограничение на (col1,col2)
, имате работа с учебник UPSERT
ситуация. Тук можете да намерите много свързани въпроси и отговори.
Като цяло, ако някакви ограничението е нарушено, се създава изключение, което (освен ако не е попаднало в подтранзакция, както е възможно в процедурен език от страна на сървъра като plpgsql) ще върне не само на изявлението, но и на цялата транзакция .
Без едновременни записи
Т.е.:Никакви други транзакции няма да се опитват да запишат в същата таблица по едно и също време.
-
Изключете редове, които вече са в таблицата с
WHERE NOT EXISTS ...
или всяка друга приложима техника: -
Изберете редове, които не присъстват в друга таблица
-
И не забравяйте да премахнете дубликатите вътре вмъкнатият набор също, което не да бъдат изключени от полу-анти-съединяване
WHERE NOT EXISTS ...
Една техника за справяне с двете едновременно би била EXCEPT
:
INSERT INTO tbl (col1, col2)
VALUES
(text 'v1', text 'v2') -- explicit type cast may be needed in 1st row
, ('v3', 'v4')
, ('v3', 'v4') -- beware of dupes in source
EXCEPT SELECT col1, col2 FROM tbl;
EXCEPT
без ключовата дума ALL
сгъва дублиращи се редове в източника. Ако знаете, че няма дубликати или не искате да сгъвате дубликати безшумно, използвайте EXCEPT ALL
(или някоя от другите техники). Вижте:
- Използване на клауза EXCEPT в PostgreSQL
Обикновено, ако целевата таблица е голяма , WHERE NOT EXISTS
в комбинация с DISTINCT
на източника вероятно ще бъде по-бърз:
INSERT INTO tbl (col1, col2)
SELECT *
FROM (
SELECT DISTINCT *
FROM (
VALUES
(text 'v1', text'v2')
, ('v3', 'v4')
, ('v3', 'v4') -- dupes in source
) t(c1, c2)
) t
WHERE NOT EXISTS (
SELECT FROM tbl
WHERE col1 = t.c1 AND col2 = t.c2
);
Ако може да има много измамници, първо си струва да ги сгънете в източника. В противен случай използвайте една подзаявка по-малко.
Свързано:
- Изберете редове, които не присъстват в друга таблица
С едновременни записи
Използвайте Postgres UPSERT
реализация INSERT ... ON CONFLICT ...
в Postgres 9.5 или по-късно:
INSERT INTO tbl (col1,col2)
SELECT DISTINCT * -- still can't insert the same row more than once
FROM (
VALUES
(text 'v1', text 'v2')
, ('v3','v4')
, ('v3','v4') -- you still need to fold dupes in source!
) t(c1, c2)
ON CONFLICT DO NOTHING; -- ignores rows with *any* conflict!
Допълнително четене:
- Как да използвам RETURNING с ON CONFLICT в PostgreSQL?
- Как да вмъкна ред, който съдържа външен ключ?
Документация:
- Ръководството
- Страницата за записване
- Уики страницата на Postgres
Референтният отговор на Крейг за UPSERT
проблеми:
- Как да UPSERT (СЛИВАНЕ, ВМЕСВАНЕ ... ПРИ ДУБЛИРАНЕ НА АКТУАЛИЗИРАНЕ) в PostgreSQL?