INSERT
po prostu wstawi wszystkie wiersze i nic wydarzy się coś wyjątkowego, chyba że masz jakieś ograniczenie zabranianie duplikatów / nakładających się wartości (PRIMARY KEY
, UNIQUE
, CHECK
lub EXCLUDE
ograniczenie) – o których nie wspomniałeś w swoim pytaniu. Ale prawdopodobnie właśnie o to się martwisz.
Zakładając UNIQUE
lub ograniczenie PK na (col1,col2)
, masz do czynienia z podręcznikiem UPSERT
sytuacja. Wiele powiązanych pytań i odpowiedzi, które można znaleźć tutaj.
Ogólnie, jeśli jakikolwiek Ograniczenie jest naruszone, zgłoszony jest wyjątek, który (chyba że jest uwięziony w podtransakcji, jak to jest możliwe w proceduralnym języku po stronie serwera, takim jak plpgsql) wycofa nie tylko instrukcję, ale całą transakcję .
Bez równoczesnych zapisów
Np. Żadna inna transakcja nie będzie próbowała pisać do tej samej tabeli w tym samym czasie.
-
Wyklucz wiersze, które są już w tabeli z
WHERE NOT EXISTS ...
lub jakakolwiek inna stosowna technika: -
Wybierz wiersze, których nie ma w innej tabeli
-
I nie zapomnij usunąć duplikatów w również wstawiony zestaw, co nie być wykluczone przez semi-anti-join
WHERE NOT EXISTS ...
Jedną z technik radzenia sobie z obydwoma na raz jest 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
bez słowa kluczowego ALL
zgina zduplikowane wiersze w źródle. Jeśli wiesz, że nie ma duplikatów lub nie chcesz po cichu składać duplikatów, użyj EXCEPT ALL
(lub jedną z innych technik). Zobacz:
- Używanie klauzuli EXCEPT w PostgreSQL
Ogólnie, jeśli tabela docelowa jest duża , WHERE NOT EXISTS
w połączeniu z DISTINCT
na źródle prawdopodobnie będzie szybciej:
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
);
Jeśli może być wiele duplikatów, opłaca się najpierw złożyć je w źródle. W przeciwnym razie użyj jednego podzapytania mniej.
Powiązane:
- Wybierz wiersze, których nie ma w innej tabeli
Z równoczesnymi zapisami
Użyj UPSERT
Postgresa implementacja INSERT ... ON CONFLICT ...
w Postgresie 9.5 lub później:
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!
Dalsza lektura:
- Jak używać RETURNING z ON CONFLICT w PostgreSQL?
- Jak wstawić wiersz zawierający klucz obcy?
Dokumentacja:
- Instrukcja
- Strona zatwierdzenia
- Strona Wiki Postgres
Referencyjna odpowiedź Craiga dla UPSERT
problemy:
- Jak UPSERT (MERGE, INSERT... W DUPLIKACIE AKTUALIZACJI) w PostgreSQL?