Функция PostgreSQL для последнего вставленного идентификатора



в PostgreSQL, как мне получить последний идентификатор, вставленный в таблицу?



в MS SQL есть SCOPE_IDENTITY ().



пожалуйста, не советуйте мне использовать что-то вроде этого:



select max(id) from table
1206   10  

10 ответов:

(tl;dr: перейти вариант 3: вставить с возвратом)

Напомним, что в postgresql нет понятия " id " для таблиц, просто последовательности (которые обычно, но не обязательно использоваться в качестве значений по умолчанию для суррогатных первичных ключей, с серийный псевдо-тип).

если вы заинтересованы в получении идентификатор вставленной строки, есть несколько способов:


Вариант 1: CURRVAL(<sequence name>);.

например:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval('persons_id_seq');

имя последовательности должно быть известно, это действительно произвольно; в этом примере мы предполагаем, что таблица persons есть id столбец, созданный с помощью 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, если дополнительные вставки выполняются в то же самое persons таблица (это гораздо менее обычно, но риск все еще существует).


Вариант 3: INSERT С RETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

это самый чистый, эффективный и безопасный способ получить идентификатор. У него нет ни одного из рисков предыдущего.

недостатки? Почти нет: вам может потребоваться изменить способ вызова инструкции INSERT (в худшем случае, возможно, ваш уровень API или DB не ожидает, что вставка вернет значение); это не стандартный SQL (кто заботится); он доступен с Postgresql 8.2 (Dec 2006...)


Вывод: Если вы можете, перейдите к варианту 3. В другом месте, предпочитаю 1.

Примечание: все эти методы бесполезны, если вы намерены сделать последний глобально вставленный идентификатор (не обязательно в вашей сессии). Для этого необходимо прибегнуть к 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];

обратите внимание, что есть два предложения INTO. Поэтому функция 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 для вашей последовательности), затем сбросьте последовательность обратно к исходному значению, передав ложный флаг:

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;

Надежда может помочь.

Comments

    Ничего не найдено.