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?