Mam tabelę tag
z 2 kolumnami: id
(uuid) i name
(tekst). Chcę teraz wstawić nowy znacznik do tabeli, ale jeśli znacznik już istnieje, chcę po prostu pobrać id
istniejący rekord.
Zakładałem, że mogę po prostu użyć ON CONFLICT DO NOTHING
w połączeniu z RETURNING "id"
:
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT DO NOTHING
RETURNING "id";
Zwraca to jednak pusty zestaw wyników, jeśli znacznik o nazwie „foo” już istnieje.
Następnie zmieniłem zapytanie, aby użyć DO UPDATE
klauzuli noop :
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT ("name") DO UPDATE SET "name" = 'foo'
RETURNING "id";
Działa to zgodnie z przeznaczeniem, ale jest nieco mylące, ponieważ po prostu ustawiam nazwę na już istniejącą wartość.
Czy to jest sposób na rozwiązanie tego problemu, czy brakuje mi prostszego podejścia?
postgresql
upsert
postgresql-9.5
Der Hochstapler
źródło
źródło
returning excluded.id
?ERROR: missing FROM-clause entry for table "excluded"
podczas korzystaniaDO NOTHING
.Odpowiedzi:
Będzie to działać (o ile testowałem) we wszystkich 3 przypadkach, jeśli wartości do wstawienia są nowe lub wszystkie już znajdują się w tabeli lub mieszance:
Prawdopodobnie istnieją inne sposoby, aby to zrobić, być może bez użycia nowej
ON CONFLICT
składni.źródło
Nie mam pojęcia, jak to będzie działać, ale jako kolejna opcja do wypróbowania, tutaj robi to samo w oldschoolowy sposób (bez
ON CONFLICT
):Oznacza to, że wstaw tylko [unikalne] nazwy nie znalezione w
tag
tabeli i zwróć identyfikatory; połącz to z identyfikatorami nazw, które istnieją wtag
celu uzyskania ostatecznego wyniku. Możesz także wrzucićname
dane wyjściowe, zgodnie z sugestią ypercubeᵀᴹ , abyś wiedział, który identyfikator pasuje do której nazwy.źródło
SELECT .. FROM ins UNION ALL SELECT ... FROM val JOIN tag ... ;