INSERT
kommer bara att infoga alla rader och ingenting speciell kommer att hända, om inte du har någon form av begränsning inte tillåta dubbletter/överlappande värden (PRIMARY KEY
, UNIQUE
, CHECK
eller EXCLUDE
constraint) - som du inte nämnde i din fråga. Men det är det du förmodligen är orolig för.
Förutsatt en UNIQUE
eller PK-begränsning på (col1,col2)
, du har att göra med en lärobok UPSERT
situation. Många relaterade frågor och svar hittar du här.
I allmänhet, om någon begränsningen överträds, ett undantag tas upp som (såvida det inte är instängt i deltransaktion som det är möjligt i ett procedurspråk på serversidan som plpgsql) kommer att rulla tillbaka inte bara uttalandet utan hela transaktionen .
Utan samtidiga skrivningar
Dvs:Inga andra transaktioner kommer att försöka skriva till samma tabell samtidigt.
-
Exkludera rader som redan finns i tabellen med
WHERE NOT EXISTS ...
eller någon annan tillämplig teknik: -
Välj rader som inte finns i andra tabeller
-
Och glöm inte att ta bort dubbletter inom den infogade uppsättningen också, vilket inte skulle göra uteslutas av semi-anti-join
WHERE NOT EXISTS ...
En teknik för att hantera båda samtidigt skulle vara 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
utan nyckelordet ALL
viker dubblettrader i källan. Om du vet att det inte finns några duper, eller om du inte vill vika dubbletter tyst, använd EXCEPT ALL
(eller någon av de andra teknikerna). Se:
- Använder EXCEPT-satsen i PostgreSQL
I allmänhet, om måltabellen är stor , WHERE NOT EXISTS
i kombination med DISTINCT
på källan kommer förmodligen att vara snabbare:
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
);
Kan det bli många duper lönar det sig att vika in dem i källan först. Använd annars en underfråga mindre.
Relaterat:
- Välj rader som inte finns i andra tabeller
Med samtidiga skrivningar
Använd Postgres UPSERT
implementering INSERT ... ON CONFLICT ...
i Postgres 9.5 eller senare:
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!
Mer läsning:
- Hur använder man RETURNING med ON CONFLICT i PostgreSQL?
- Hur infogar jag en rad som innehåller en främmande nyckel?
Dokumentation:
- Handboken
- Bekräftelsesidan
- Postgres Wiki-sida
Craigs referenssvar för UPSERT
problem:
- Hur UPSERT (SLÄNTA, INFOGA ... PÅ DUBLIKAT UPPDATERING) i PostgreSQL?