Funkcja PostgreSQL dla Ostatnio wstawionego ID
W PostgreSQL, Jak mogę wstawić ostatni id do tabeli?
W MS SQL jest SCOPE_IDENTITY ().
Proszę nie radzić mi używać czegoś takiego:
select max(id) from table
10 answers
( tl;dr
: goto option 3: INSERT with RETURNING)
Przypomnijmy, że w postgresql nie ma pojęcia "id" dla tabel, tylko sekwencje (które są zazwyczaj, ale niekoniecznie muszą być używane jako domyślne wartości dla zastępczych kluczy podstawowych, z pseudo-typem } szeregowy).
Jeśli jesteś zainteresowany uzyskaniem id nowo wstawionego wiersza, istnieje kilka sposobów:
Opcja 1: CURRVAL(<sequence name>);
.
Na przykład:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
The nazwa sekwencji musi być znana, jest naprawdę Dowolna; w tym przykładzie zakładamy, że Tabela persons
ma kolumnę id
utworzoną z pseudo-typu SERIAL
. Aby uniknąć polegania na tym i czuć się bardziej czystym, możesz użyć zamiast tego pg_get_serial_sequence
:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
Zastrzeżenie: currval()
działa tylko po INSERT
(który wykonał nextval()
), w tej samej sesji .
Opcja 2: LASTVAL();
Jest to podobne do poprzedniego, tylko, że nie trzeba podaj nazwę sekwencji: wyszukuje najnowszą zmodyfikowaną sekwencję (zawsze wewnątrz sesji, to samo zastrzeżenie jak powyżej).
Zarówno CURRVAL
jak i LASTVAL
są całkowicie bezpieczne. Zachowanie sekwencji w PG jest tak zaprojektowane, aby różne sesje nie przeszkadzały, więc nie ma ryzyka warunków wyścigu (jeśli inna sesja wstawi inny wiersz między moją wstawką a moim SELECT, nadal otrzymuję poprawną wartość).
Jednak [26]} mają subtelny potencjał problem. Jeśli baza danych posiada jakąś TRIGGER (lub regułę), która po wstawieniu do tabeli persons
powoduje dodatkowe Wstawienia w innych tabelach... wtedy LASTVAL
prawdopodobnie poda nam złą wartość. Problem może wystąpić nawet z CURRVAL
, Jeśli dodatkowe wstawki są wykonywane w tej samej tabeli persons
(jest to znacznie mniej typowe, ale ryzyko nadal istnieje).
Opcja 3: INSERT
Z RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
Jest to najbardziej czysty, skuteczny i bezpieczny sposób na uzyskanie identyfikatora. To nie ma ŻADNEGO RYZYKA z poprzedniego.
Wady? Prawie żaden: być może będziesz musiał zmodyfikować sposób wywoływania instrukcji INSERT (w najgorszym przypadku, być może Twoja warstwa API lub DB nie oczekuje, że INSERT zwróci wartość); nie jest to standardowy SQL (kogo to obchodzi); jest dostępny od Postgresql 8.2 (grudzień 2006...)
Wniosek: jeśli możesz, wybierz opcję 3. Gdzie indziej, wolę 1.
Uwaga: wszystkie te metody są bezużyteczne, jeśli zamierzasz uzyskać ostatnią globalnie wstawiony id (niekoniecznie w sesji). W tym celu musisz użyć select max(id) from table
(oczywiście nie będzie to odczytywać niezatwierdzonych wstawek z innych transakcji).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-14 04:28:04
Patrz klauzula zwracająca INSERT . Zasadniczo INSERT podwaja się jako zapytanie i zwraca wartość, która została wstawiona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-31 15:01:33
Możesz użyć klauzuli zwracającej w instrukcji INSERT, tak jak poniżej
wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
id
----
3
(1 row)
INSERT 0 1
wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
2
(1 row)
INSERT 0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-24 10:25:36
Odpowiedź Leonbloy jest całkiem 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:
CREATE TABLE person(
id serial,
lastname character varying (50),
firstname character varying (50),
CONSTRAINT person_pk PRIMARY KEY (id)
);
CREATE TABLE client (
id integer,
CONSTRAINT client_pk PRIMARY KEY (id),
CONSTRAINT fk_client_person FOREIGN KEY (id)
REFERENCES person (id) MATCH SIMPLE
);
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 zajmuje się wstawianiem nowego rekordu osoby. W tym celu musimy użyć lekkiego wariantu wariantu 3 leonbloy ' a:
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
Zauważ, że istnieją dwie klauzule INTO. Dlatego funkcja PL / pgSQL będzie zdefiniowana następująco:
CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
RETURNS integer AS
$BODY$
DECLARE
v_id integer;
BEGIN
-- Inserts the new person record and retrieves the last inserted id
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO v_id;
-- Inserts the new client and references the inserted person
INSERT INTO client(id) VALUES (v_id);
-- Return the new id so we can use it in a select clause or return the new id into the user application
RETURN v_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
Teraz możemy wstawić nowe dane używając:
SELECT new_client('Smith', 'John');
Lub
SELECT * FROM new_client('Smith', 'John');
I otrzymujemy nowo utworzony identyfikator.
new_client
integer
----------
1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:18
Zobacz poniższy przykład
CREATE TABLE users (
-- make the "id" column a primary key; this also creates
-- a UNIQUE constraint and a b+-tree index on the column
id SERIAL PRIMARY KEY,
name TEXT,
age INT4
);
INSERT INTO users (name, age) VALUES ('Mozart', 20);
Następnie dla uzyskania ostatnio wstawionego id użyj tego dla tabeli "user" seq nazwa kolumny " id "
SELECT currval(pg_get_serial_sequence('users', 'id'));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-04 15:47:48
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))
Musisz oczywiście podać nazwę tabeli i nazwę kolumny.
To będzie dla bieżącej sesji / połączenia http://www.postgresql.org/docs/8.3/static/functions-sequence.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-04 15:51:34
Dla tych, którzy muszą uzyskać rekord wszystkich danych, możesz dodać
returning *
Na koniec zapytania, aby uzyskać obiekt all wraz z id.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 07:45:00
Spróbuj tego:
select nextval('my_seq_name'); // Returns next value
Jeśli zwróci 1 (lub jakąkolwiek wartość startową dla Twojej sekwencji), zresetuj sekwencję z powrotem do pierwotnej wartości, przekazując fałszywą flagę:
select setval('my_seq_name', 1, false);
Inaczej,
select setval('my_seq_name', nextValue - 1, true);
Spowoduje przywrócenie wartości sekwencji do stanu pierwotnego, a" setval " powróci z wartością sekwencji, której szukasz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-27 18:09:30
Postgres ma wbudowany mechanizm tego samego, który w tym samym zapytaniu zwraca id lub cokolwiek chcesz, aby zapytanie zwróciło. oto przykład. Załóżmy, że masz utworzoną tabelę, która ma kolumny 2 column1 i column2 i chcesz, aby kolumna 1 była zwracana po każdej wstawce.
# create table users_table(id serial not null primary key, name character varying);
CREATE TABLE
#insert into users_table(name) VALUES ('Jon Snow') RETURNING id;
id
----
1
(1 row)
# insert into users_table(name) VALUES ('Arya Stark') RETURNING id;
id
----
2
(1 row)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-30 11:49:44
Jeśli potrzebujesz tylko pobrać ostatnio wstawiony identyfikator bez wstawiania czegokolwiek, możesz użyć poniższego przykładu
SELECT id FROM users ORDER BY id DESC LIMIT 1;
Nadzieja może pomóc.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-21 13:14:21