Как использовать currval () в PostgreSQL для получения последнего вставленного идентификатора?

У меня есть таблица:

  Названия CREATE TABLE (идентификатор serial, имя varchar (20))
 

Я хочу «последний вставленный идентификатор» из этой таблицы, не используя RETURNING id при вставке. Кажется, существует функция CURRVAL () , но Я не понимаю, как его использовать.

Я пробовал с:

  SELECT CURRVAL () AS id FROM names_id_seq
SELECT CURRVAL ('names_id_seq')
SELECT CURRVAL ('names_id_seq' :: regclass)
 

, но никто из них не работает. Как я могу использовать currval () , чтобы получить последний вставленный идентификатор?

42 голоса | спросил Jonas 13 J0000006Europe/Moscow 2011, 12:20:20

6 ответов


38

Если вы создаете столбец как serial PostgreSQL автоматически создает для этого последовательность.

Имя последовательности автогенерируется и всегда является tablename_columnname_seq, в вашем случае последовательность будет иметь имена names_id_seq .

После вставки в таблицу вы можете вызвать currval () с этим именем последовательности:

  Postgres = & GT; Имена CREATE TABLE в имени schema_name (идентификатор serial, имя varchar (20));
СОЗДАТЬ ТАБЛИЦУ
Postgres = & GT; вставлять в имена (имя) значения ('Arthur Dent');
INSERT 0 1
Postgres = & GT; выберите currval ('names_id_seq');
 CURRVAL
---------
       1
(1 ряд)
Postgres = & GT;
 
ответил a_horse_with_no_name 13 J0000006Europe/Moscow 2011, 15:08:21
26

Это прямо из Переполнение стека

Как было указано @a_horse_with_no_name и @Jack Douglas, currval работает только с текущим сеансом. Поэтому, если вы в порядке с тем, что на результат может повлиять незафиксированная транзакция другого сеанса, и вы все еще хотите что-то, что будет работать через сеансы, вы можете использовать это:

  SELECT last_value FROM your_sequence_name;
 

Используйте ссылку для SO для получения дополнительной информации.

Из документации Postgres , хотя четко указано, что

  

Ошибка вызова lastval, если nextval еще не был вызван в текущем сеансе.

Итак, я думаю, строго говоря, чтобы правильно использовать currval или last_value для последовательности через сеансы, вам нужно было бы сделать что-то подобное?

  SELECT setval ('serial_id_seq', nextval ('serial_id_seq') - 1);
 

Предполагая, что у вас не будет вставки или какого-либо другого способа использования серийного поля в текущем сеансе.

ответил Slak 2 +04002014-10-02T14:51:38+04:00312014bEurope/MoscowThu, 02 Oct 2014 14:51:38 +0400 2014, 14:51:38
12

Вы необходимо вызвать nextval для этой последовательности в этом сеансе до CURRVAL :

  создать последовательность серий;
выберите nextval ('serial');
 NEXTVAL
---------
       1
(1 ряд)

выберите currval ('serial');
 CURRVAL
---------
       1
(1 ряд)
 

, поэтому вы не можете найти «последний вставленный идентификатор» из последовательности, если только insert не выполняется в том же сеансе (транзакция может отбросить, но последовательность не будет)

, как указано в ответе a_horse, create table с столбцом типа serial будет автоматически создавать последовательность и использовать ее для генерации значения по умолчанию для столбца, поэтому insert обычно выполняет неявное обращение к nextval :

  создать таблицу my_table (id serial);
УВЕДОМЛЕНИЕ: CREATE TABLE создаст неявную последовательность «my_table_id_seq» для
         последовательный столбец "my_table.id"

\ d my_table
                          Таблица "stack.my_table"
 Колонка | Тип | Модификаторы
-------- + --------- + ------------------------------- ------------------------
 id | целое число | not null default nextval ('my_table_id_seq' :: regclass)

вставить в значения по умолчанию my_table;
выберите currval ('my_table_id_seq');
 CURRVAL
---------
       1
(1 ряд)
 
ответил Jack Douglas 13 J0000006Europe/Moscow 2011, 12:37:08
1

Итак, есть несколько проблем с этими различными способами:

Currval получает только последнее значение, сгенерированное в текущем сеансе - это здорово, если у вас нет ничего другого, генерирующего значения, но в тех случаях, когда вы можете вызвать триггер и /или иметь последовательность, расширенную более одного раза в текущая транзакция не вернет правильное значение. Это не проблема для 99% людей там, но это то, что нужно принимать во внимание.

Лучший способ получить уникальный идентификатор, назначенный после операции вставки, - это использование предложения RETURNING. В приведенном ниже примере предполагается, что столбец, связанный с последовательностью, называется «id»:

  вставить в значения таблицы A (cola, colb, colc) ('val1', 'val2', 'val3') return id;
 

Обратите внимание, что полезность предложения RETURNING выходит за рамки простого получения последовательности, так как она также будет:

  • Возвращаемые значения, которые использовались для «окончательной вставки» (после того, как, например, триггер BEFORE мог изменить введенные данные.)
  • Верните значения, которые были удалены:

    удалить из таблицы A, где id> 100 возврат *

  • Верните измененные строки после UPDATE:

    таблица обновлений. Набор X = 'y', где blah = 'blech' возвращает *

  • Используйте результат удаления для обновления:

    WITH A as (удалить * из таблицы A в качестве возвращаемого id) update B set deleted = true, где id in (выберите id из A);

ответил chander 4 PM00000050000003331 2017, 17:35:33
0

Мне пришлось выполнить запрос, несмотря на использование SQLALchemy, потому что мне не удалось использовать currval.

  nextId = db.session.execute ("select last_value from <table> _seq"). fetchone () [0] + 1
 

Это был проект python flask + postgresql.

ответил Jalal 12 Jpm1000000pmTue, 12 Jan 2016 19:24:27 +030016 2016, 19:24:27
-2

Различные версии PostgreSQL могут иметь разные функции для получения текущего или следующего идентификатора последовательности.

Сначала вы должны знать версию своих Postgres. Использование select version (); чтобы получить версию.

В PostgreSQL 8.2.15 вы получаете текущий идентификатор последовательности, используя select last_value from schemaName.sequence_name .

Если вышеуказанный оператор не работает, вы можете использовать select currval ('schemaName.sequence_name');

ответил Robin 28 +03002015-10-28T19:07:17+03:00312015bEurope/MoscowWed, 28 Oct 2015 19:07:17 +0300 2015, 19:07:17

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132