W PostgreSQL, jak mogę wstawić ostatni identyfikator do tabeli?
W MS SQL jest SCOPE_IDENTITY ().
Proszę nie doradzać mi używania czegoś takiego:
select max(id) from table
postgresql
insert
lastinsertid
Anton
źródło
źródło
Odpowiedzi:
(
tl;dr
: goto opcja 3: WSTAWIANIE Z POWROTEM)Przypomnijmy, że w postgresql nie ma pojęcia „id” dla tabel, tylko sekwencje (które są zwykle, ale niekoniecznie używane jako wartości domyślne dla zastępczych kluczy podstawowych, z pseudo-typem SERIAL ).
Jeśli chcesz uzyskać identyfikator nowo wstawionego wiersza, istnieje kilka sposobów:
Wariant 1:
CURRVAL(<sequence name>);
.Na przykład:
Nazwa sekwencji musi być znana, to naprawdę dowolne; w tym przykładzie zakładamy, że tabela
persons
maid
kolumnę utworzoną za pomocąSERIAL
pseudo-typu. Aby uniknąć polegania na tym i poczuć się czystszym, możesz zamiast tego użyćpg_get_serial_sequence
:Zastrzeżenie:
currval()
działa tylko poINSERT
(który wykonałnextval()
), w tej samej sesji .Opcja 2:
LASTVAL();
Jest to podobne do poprzedniego, tyle że nie musisz określać nazwy sekwencji: szuka najnowszej zmodyfikowanej sekwencji (zawsze w sesji, z tym samym zastrzeżeniem jak powyżej).
Zarówno
CURRVAL
iLASTVAL
są całkowicie zbieżne bezpieczne. Zachowanie sekwencji w PG jest zaprojektowane tak, aby inna sesja nie przeszkadzała, więc nie ma ryzyka warunków wyścigu (jeśli inna sesja wstawi kolejny wiersz między moim INSERT a moim SELECT, nadal otrzymuję swoją prawidłową wartość).Jednak oni mają subtelny potencjalny problem. Jeśli baza danych ma TRIGGER (lub ZASADĘ), która po wstawieniu do
persons
tabeli powoduje dodatkowe wstawienia w innych tabelachLASTVAL
, prawdopodobnie poda nam niewłaściwą wartość. Problem może się nawet zdarzyćCURRVAL
, jeśli dodatkowe wstawienia zostaną wykonane w tej samejpersons
tabeli (jest to znacznie mniej normalne, ale ryzyko nadal istnieje).Opcja 3:
INSERT
zRETURNING
Jest to najbardziej czysty, wydajny i bezpieczny sposób na uzyskanie identyfikatora. Nie ma żadnego ryzyka z poprzedniego.
Wady Prawie żaden: może być konieczna modyfikacja sposobu wywoływania instrukcji INSERT (w najgorszym przypadku warstwa API lub DB nie spodziewa się, że INSERT zwróci wartość); to nie jest standardowy SQL (kogo to obchodzi); jest dostępny od Postgresql 8.2 (grudzień 2006 ...)
Wniosek: jeśli możesz, wybierz opcję 3. W innym miejscu, wybierz 1.
Uwaga: wszystkie te metody są bezużyteczne, jeśli zamierzasz uzyskać ostatni wstawiony identyfikator globalnie (niekoniecznie przez twoją sesję). W tym celu należy skorzystać
SELECT max(id) FROM table
(oczywiście nie odczyta to nieprzypisanych wstawek z innych transakcji).I odwrotnie, nigdy nie powinieneś używać
SELECT max(id) FROM table
jednej z 3 powyższych opcji, aby uzyskać identyfikator wygenerowany właśnie przez twojąINSERT
instrukcję, ponieważ (oprócz wydajności) nie jest to jednocześnie bezpieczne: między twojąINSERT
aSELECT
inną sesją mogło wstawić inny rekord.źródło
SELECT max(id)
niestety nie wykonuje zadania, gdy tylko zaczniesz usuwać wiersze.1,2,3,4,5
i usuwasz wiersze 4 i 5, ostatni wstawiony identyfikator to wciąż 5, alemax()
zwraca 3.RETURNING id;
aby wstawić to do innej tabeli!RETURNING id
z skryptu SQL dostarczanego dopsql
narzędzia wiersza poleceń?Zobacz klauzulę RETURNING instrukcji INSERT . Zasadniczo INSERT pełni również funkcję zapytania i zwraca wartość, która została wstawiona.
źródło
insert into names (firstname, lastname) values ('john', 'smith') returning id;
to po prostu wyświetla id tak, jakbyś działałselect id from names where id=$lastid
bezpośrednio. Jeśli chcesz zapisać zwrot w zmiennej , toinsert into names (firstname, lastname) values ('john', 'smith') returning id into other_variable;
jeśli instrukcja zawierająca zwracaną wartość jest ostatnią instrukcją w funkcji , wówczas identyfikator, któryreturning
jest zwracany, jest zwracany przez funkcję jako całość.możesz użyć klauzuli RETURNING w instrukcji INSERT, podobnie jak poniżej
źródło
Odpowiedź Leonbloya jest dość kompletna. Dodałbym tylko specjalny przypadek, w którym trzeba uzyskać ostatnią wstawioną wartość z funkcji PL / pgSQL, gdzie OPCJA 3 nie pasuje dokładnie.
Na przykład, jeśli mamy następujące tabele:
Jeśli musimy wstawić rekord klienta, musimy odwołać się do rekordu osoby. Ale powiedzmy, że chcemy opracować funkcję PL / pgSQL, która wstawia nowy rekord do klienta, ale także dba o wstawienie rekordu nowej osoby. W tym celu musimy użyć niewielkiej odmiany OPCJI 3 firmy leonbloy:
Zauważ, że istnieją dwie klauzule INTO. Dlatego funkcję PL / pgSQL można zdefiniować następująco:
Teraz możemy wstawić nowe dane za pomocą:
lub
I otrzymujemy nowo utworzony identyfikator.
źródło
Dla tych, którzy potrzebują uzyskać wszystkie dane, możesz dodać
na końcu zapytania, aby uzyskać cały obiekt, w tym identyfikator.
źródło
Zobacz poniższy przykład
Następnie, aby uzyskać ostatni wstawiony identyfikator, użyj tego dla tabeli „user” seq nazwa kolumny „id”
źródło
Musisz oczywiście podać nazwę tabeli i nazwę kolumny.
Dotyczy to bieżącej sesji / połączenia http://www.postgresql.org/docs/8.3/static/functions-sequence.html
źródło
Spróbuj tego:
Jeśli to zwróci 1 (lub cokolwiek to jest wartość_początkowa dla sekwencji), następnie zresetuj sekwencję z powrotem do pierwotnej wartości, przekazując flagę false:
Inaczej,
Spowoduje to przywrócenie wartości sekwencji do pierwotnego stanu, a „setval” powróci z poszukiwaną wartością sekwencji.
źródło
Postgres ma wbudowany mechanizm dla tego samego, który w tym samym zapytaniu zwraca id lub cokolwiek, co chcesz zwrócić zapytanie. Oto przykład. Załóżmy, że masz utworzoną tabelę z 2 kolumnami kolumna 1 i kolumna 2 i chcesz, aby kolumna 1 była zwracana po każdej wstawce.
źródło
Miałem ten problem z Javą i Postgres. Naprawiłem to, aktualizując nową wersję Connector-J.
postgresql-9.2-1002.jdbc4.jar
https://jdbc.postgresql.org/download.html : Wersja 42.2.12
https://jdbc.postgresql.org/download/postgresql-42.2.12.jar
źródło