PostgreSQL следующее значение последовательностей?

Я использую PostgreSQL для моего сайта Codeigniter. Я использую продуктовый Crud для операций добавления, редактирования и удаления. При редактировании или добавлении я хочу динамически переименовывать загруженный файл на основе идентификатора содержимого. Я могу сделать это с помощью бакалеи Crud's callback_after_upload функция.

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

Или есть простой способ сделать это?

8 ответов

RETURNING

В современном PostgreSQL (8.2 или более поздней версии) вы делаете это с помощью одного обращения к базе данных:

INSERT INTO tbl(filename)
VALUES ('my_filename')
RETURNING tbl_id;

tbl_id быть serial колонка. Подробнее в руководстве.

Явно получить значение

Если filename необходимо включить tbl_id (избыточно), вы все еще можете использовать один запрос.
использование lastval() или более конкретный currval():

INSERT INTO tbl (filename)
VALUES ('my_filename' || lastval())  -- or currval('tbl_tbl_id_seq')
RETURNING tbl_id;

Руководство о lastval() :

Эта функция идентична currval за исключением того, что вместо того, чтобы брать имя последовательности в качестве аргумента, он выбирает значение последней последовательности, использованной nextval в текущем сеансе.

Если у вас есть (или может быть) несколько последовательностей, связанных с таблицей (даже с помощью триггеров или других побочных эффектов), верный способ - использовать currval('tbl_tbl_id_seq'),

Наименование последовательности

Строковый литерал 'tbl_tbl_id_seq' в моем примере предполагается, что это фактическое имя последовательности и приведено к regclass, что вызывает исключение, если в текущем не может быть найдена последовательность с таким именем search_path,

tbl_tbl_id_seq автоматически генерируется по умолчанию для таблицы tbl с серийным столбцом tbl_id, Но нет никаких гарантий. Столбец по умолчанию может извлекать значения из любой последовательности, если это определено. И если имя по умолчанию берется при создании таблицы, Postgres выбирает следующее свободное имя в соответствии с жестко заданным алгоритмом.

Если вы не знаете название последовательности для serial столбец, найдите его с помощью специальной функции pg_get_serial_sequence(), Можно даже сделать на лету:

INSERT INTO tbl (filename)
VALUES ('my_filename' || currval(pg_get_serial_sequence('tbl', 'tbl_id'))
RETURNING tbl_id;

SQL Fiddle.

Доступ к ранее полученному значению последовательности осуществляется с помощью currval() функция.

Но это только вернет значение, если nextval() был вызван до этого.

Нет абсолютно никакого способа "заглянуть" на следующее значение последовательности, не получив его на самом деле.

Но ваш вопрос неясен. Если вы позвоните nextval() перед выполнением вставки вы можете использовать это значение во вставке. Или даже лучше, используйте currval() в вашем заявлении вставки:

select nextval('my_sequence') ...

... do some stuff with the obtained value

insert into my_table(id, filename)
values (currval('my_sequence'), 'some_valid_filename');

Я наткнулся на этот вопрос, потому что я пытался найти следующее значение последовательности по таблице. Это не ответило на мой вопрос, но вот как это делается, и это может помочь тем, кто ищет значение последовательности не по имени, а по таблице:

SELECT nextval(pg_get_serial_sequence('<your_table>', 'id')) AS new_id; 

Надеюсь, это поможет:)

Ответ на 2022 год

Вы можете использовать pg_sequence_last_value() , если знаете имя последовательности:

      SELECT pg_sequence_last_value('public.person_id_seq');

Если вы не в сеансе, вы можете просто nextval('you_sequence_name'), и это просто отлично.

Чтобы ответить на ваш вопрос буквально, вот как получить следующее значение последовательности, не увеличивая его:

SELECT
 CASE WHEN is_called THEN
   last_value + 1
 ELSE
   last_value
 END
FROM sequence_name

Очевидно, что не стоит использовать этот код на практике. Нет гарантии, что в следующей строке действительно будет этот идентификатор. Однако для целей отладки может быть интересно узнать значение последовательности, не увеличивая ее, и вот как вы можете это сделать.

Я попробовал это, и это прекрасно работает

@Entity
public class Shipwreck {
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
  @Basic(optional = false)
  @SequenceGenerator(name = "seq", sequenceName = "shipwreck_seq", allocationSize = 1)
  Long id;

....

CREATE SEQUENCE public.shipwreck_seq
    INCREMENT 1
    START 110
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

Даже если это можно каким-то образом сделать, это ужасная идея, поскольку можно было бы получить последовательность, которая затем будет использоваться другой записью!

Гораздо лучшая идея - сохранить запись, а затем извлечь последовательность.

Другие вопросы по тегам