Niektóre serwery SQL mają funkcję, która INSERT
jest pomijana, jeśli naruszyłoby to ograniczenie klucza podstawowego / unikalnego. Na przykład MySQL ma INSERT IGNORE
.
Jaki jest najlepszy sposób na emulację INSERT IGNORE
i ON DUPLICATE KEY UPDATE
używanie PostgreSQL?
database
postgresql
rules
gpilotino
źródło
źródło
ON DUPLICATE KEY UPDATE
na PgSQL 9.5 jest nadal trochę niemożliwa, ponieważON CLAUSE
odpowiednik PgSQL wymaga podania nazwy ograniczenia, podczas gdy MySQL może przechwycić każde ograniczenie bez potrzeby jego definiowania. Uniemożliwia mi to „emulowanie” tej funkcji bez przepisywania zapytań.Odpowiedzi:
Spróbuj wykonać AKTUALIZACJĘ. Jeśli nie modyfikuje żadnego wiersza, co oznacza, że nie istniał, więc zrób wstawianie. Oczywiście robisz to w ramach transakcji.
Możesz oczywiście zawinąć to w funkcję, jeśli nie chcesz umieszczać dodatkowego kodu po stronie klienta. Potrzebujesz także pętli dla bardzo rzadkich warunków wyścigu w tym myśleniu.
Przykład tego można znaleźć w dokumentacji: http://www.postgresql.org/docs/9.3/static/plpgsql-control-structures.html , przykład 40-2 na dole.
To zwykle najłatwiejszy sposób. Możesz zrobić trochę magii z zasadami, ale prawdopodobnie będzie to dużo bardziej bałagan. Poleciłbym podejście polegające na zawijaniu funkcji każdego dnia.
Działa to dla wartości w jednym wierszu lub w kilku wierszach. Jeśli masz do czynienia z dużą liczbą wierszy, na przykład z podzapytania, najlepiej jest podzielić je na dwa zapytania, jedno dla WSTAWIANIA i jedno dla AKTUALIZACJI (oczywiście jako odpowiednie sprzężenie / podwybór - nie ma potrzeby wpisywania głównego filtruj dwukrotnie)
źródło
INSERT ... ON CONFLICT DO NOTHING;
. Zobacz też odpowiedź stackoverflow.com/a/34639631/2091700 .MERGE
jest nie sejfu upsert współbieżności, chyba że wziąćLOCK TABLE
pierwszy. Ludzie używają tego w ten sposób, ale to jest złe.W PostgreSQL 9.5 jest to teraz natywna funkcjonalność (podobnie jak MySQL od kilku lat):
...
źródło
Edycja: jeśli przegapiłeś odpowiedź Warrena, PG9.5 ma to teraz natywnie; czas na upgrade!
Opierając się na odpowiedzi Billa Karwina, aby wyjaśnić, jak wyglądałoby podejście oparte na regułach (przenoszenie z innego schematu w tej samej bazie danych i przy użyciu wielokolumnowego klucza podstawowego):
Uwaga: reguła ma zastosowanie do wszystkich
INSERT
operacji, dopóki reguła nie zostanie usunięta, więc nie całkiem ad hoc.źródło
another_schema.my_table
zawiera duplikaty zgodnie z ograniczeniamimy_table
?INSERT INTO "my_table" SELECT DISTINCT ON (pk_col_1, pk_col_2) * FROM the_tmp_table;
DELETE FROM my_table WHERE ctid IN (SELECT ctid FROM (SELECT ctid,ROW_NUMBER() OVER (PARTITION BY pk_col_1,pk_col_2) AS rn FROM my_table) AS dups WHERE dups.rn > 1);
Dla tych z Was, którzy mają Postgres 9.5 lub nowszy, nowa składnia ON CONFLICT DO NIC powinna działać:
Dla tych z nas, którzy mają wcześniejszą wersję, to prawo łączenia będzie działać zamiast:
źródło
Unique violation: 7 ERROR: duplicate key value violates unique constraint
kiedytarget_table
wstawiono inny wiersz do niego podczas wykonywania tego zapytania, jeśli ich klucze rzeczywiście się duplikują. Wierzę, że blokowanietarget_table
pomoże, ale współbieżność oczywiście ucierpi.ON CONFLICT (field_one) DO NOTHING
to najlepsza część odpowiedzi.Aby uzyskać logikę wstawiania ignorowania , możesz zrobić coś jak poniżej. Zauważyłem, że po prostu wstawianie wartości dosłownych z instrukcji select działa najlepiej, a następnie możesz zamaskować zduplikowane klucze za pomocą klauzuli NOT EXISTS. Podejrzewam, że aby uzyskać aktualizację zduplikowanej logiki, potrzebna byłaby pętla pl / pgsql.
źródło
źródło
Wygląda na to, że PostgreSQL obsługuje obiekt schematu o nazwie a regułą .
http://www.postgresql.org/docs/current/static/rules-update.html
Możesz utworzyć regułę
ON INSERT
dla danej tabeli, robiąc to,NOTHING
jeśli istnieje wiersz z daną wartością klucza podstawowego, lub wykonującUPDATE
zamiast tego,INSERT
jeśli istnieje wiersz z daną wartością klucza podstawowego.Sam tego nie próbowałem, więc nie mogę mówić z doświadczenia ani dawać przykładu.
źródło
Jak @hanmari wspomniał w swoim komentarzu. przy wstawianiu do tabel postgres, funkcja on konfliktu (..) nic nie robi, jest najlepszym kodem, aby nie wstawiać zduplikowanych danych .:
Linia kodu ON CONFLICT pozwoli instrukcji insert na dalsze wstawianie wierszy danych. Kod zapytania i wartości to przykład wstawienia daty z Excela do tabeli dbresy postgres. Mam ograniczenia dodane do tabeli postgres, której używam, aby upewnić się, że pole ID jest unikalne. Zamiast wykonywać usuwanie wierszy danych, które są takie same, dodaję wiersz kodu sql, który przenumeruje kolumnę ID, zaczynając od 1. Przykład:
Jeśli moje dane mają pole ID, nie używam go jako podstawowego identyfikatora / identyfikatora seryjnego, tworzę kolumnę ID i ustawiam ją na serial. Mam nadzieję, że te informacje są pomocne dla wszystkich. * Nie mam wyższego wykształcenia w zakresie programowania / kodowania. Wszystko, co wiem z kodowania, uczę się sam.
źródło
To rozwiązanie pozwala uniknąć używania reguł:
ale ma wadę wydajności (patrz PostgreSQL.org ):
źródło
Zbiorczo zawsze możesz usunąć wiersz przed wstawką. Usunięcie wiersza, który nie istnieje, nie powoduje błędu, więc jest bezpiecznie pomijany.
źródło
DEFERRABLE INITIALLY DEFERRED
flagami.W przypadku skryptów importu danych, aby w pewnym sensie zastąpić „JEŚLI NIE ISTNIEJE”, istnieje nieco niezręczne sformułowanie, które jednak działa:
źródło