Функция PostgreSQL для последнего вставленного идентификатора
в PostgreSQL, как получить последний идентификатор, вставленный в таблицу?
в MS SQL есть SCOPE_IDENTITY ().
пожалуйста, не советуйте мне использовать что-то вроде этого:
select max(id) from table
10 ответов
( tl;dr
: goto вариант 3: вставить с возвратом)
Напомним, что в postgresql нет концепции " id " для таблиц, просто последовательности (которые обычно, но не обязательно использоваться в качестве значений по умолчанию для суррогатных первичных ключей, с серийный псевдо-тип).
если вы заинтересованы в получении идентификатор вставленной строки, есть несколько способов:
Вариант 1: CURRVAL(<sequence name>);
.
например:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
имя последовательности должно быть известно, это действительно произвольно; в этом примере мы предполагаем, что таблица persons
есть создан с SERIAL
псевдо-тип. Чтобы не полагаться на это и чувствовать себя более чистым, вы можете использовать вместо pg_get_serial_sequence
:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
предостережение: currval()
работает только после INSERT
(который был выполнен nextval()
), в то же сеанс.
Вариант 2: LASTVAL();
это похоже на предыдущее, только вам не нужно указывать имя последовательности: он ищет самую последнюю измененную последовательность (всегда внутри вашего сеанса, то же предостережение, что и выше).
и CURRVAL
и LASTVAL
полностью одновременный сейф. Поведение последовательности в PG сконструировано так, что различные сессии не будут мешать, поэтому нет риска гонки условия (если другой сеанс вставляет другую строку между моей вставкой и моим выбором, я все равно получаю правильное значение).
у них есть скрытый потенциал, проблемы. Если в базе данных есть некоторые триггер (или правило) что, при вставке в persons
таблица, делает некоторые дополнительные вставки в других таблицах... тогда LASTVAL
вероятно, даст нам неверное значение. Проблема может даже произойти с CURRVAL
, если дополнительные вставки сделаны intto то же persons
таблица (это гораздо менее обычно, но риск все еще существует).
Вариант 3: INSERT
С RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
это самый чистый, эффективный и безопасный способ получить id. У него нет ни одного из рисков предыдущего.
недостатки? Почти нет: вам может потребоваться изменить способ вызова инструкции INSERT (в худшем случае, возможно, ваш API или слой DB не ожидает, что INSERT вернет значение); это не стандартный SQL (кто заботится); он доступен с Postgresql 8.2 (Dec 2006...)
вывод: если вы можете, перейдите к варианту 3. В другом месте предпочитаю 1.
Примечание: все эти методы бесполезны, если вы намерены сделать последний глобально вставленный id (не обязательно в вашей сессии). Для этого вы должны прибегнуть к select max(id) from table
(конечно, это не будет читать незафиксированные вставки из других транзакций).
см. возвращающее предложение вставить заявление. В принципе, вставка удваивается как запрос и возвращает вставленное значение.
вы можете использовать предложение RETURNING в инструкции INSERT, как и следующее
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
Leonbloy по достаточно полный. Я бы только добавил частный случай, в котором нужно получить последнее вставленное значение из функции PL/pgSQL, где опция 3 не подходит точно.
например, если у нас есть следующие таблицы:
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
);
если нам нужно вставить запись клиента, мы должны ссылаться на записи человека. Но предположим, мы хотим разработать функцию PL/pgSQL, которая вставляет новую запись в клиент, но также заботится о вставке запись нового человека. Для этого мы должны использовать небольшую вариацию варианта 3 леонблоя:
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
обратите внимание,что есть два предложения. Поэтому функция PL/pgSQL будет определена следующим образом:
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;
теперь мы можем вставить новые данные с помощью:
SELECT new_client('Smith', 'John');
или
SELECT * FROM new_client('Smith', 'John');
и мы получаем вновь созданный идентификатор.
new_client
integer
----------
1
см. ниже пример
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);
затем для получения последнего вставленного идентификатора используйте это для таблицы "user" seq имя столбца "id"
SELECT currval(pg_get_serial_sequence('users', 'id'));
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))
требуется указать имя таблицы и имя столбца, конечно.
Это будет для текущего сеанса / соединения http://www.postgresql.org/docs/8.3/static/functions-sequence.html
для тех, кому нужно получить все записи данных, вы можете добавить
returning *
до конца вашего запроса, чтобы получить весь объект, включая идентификатор.
попробуйте это:
select nextval('my_seq_name'); // Returns next value
Если это возвращает 1 (или что-то еще start_value для вашей последовательности), затем сбросьте последовательность обратно в исходное значение, передав флаг false:
select setval('my_seq_name', 1, false);
иначе
select setval('my_seq_name', nextValue - 1, true);
это восстановит значение последовательности в исходное состояние, и "setval" вернется со значением последовательности, которое вы ищете.
Postgres имеет встроенный механизм для того же самого, который в том же запросе возвращает идентификатор или то, что вы хотите, чтобы запрос возвращал. вот пример. Рассмотрим, что у вас есть таблица, которая имеет 2 столбца column1 и column2, и вы хотите, чтобы column1 возвращался после каждой вставки.
# 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)
Если вам просто нужно получить последний вставленный идентификатор без вставки, вы можете использовать следующий пример
SELECT id FROM users ORDER BY id DESC LIMIT 1;
Надежда может помочь.