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;
Доступ к ранее полученному значению последовательности осуществляется с помощью 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;
Даже если это можно каким-то образом сделать, это ужасная идея, поскольку можно было бы получить последовательность, которая затем будет использоваться другой записью!
Гораздо лучшая идея - сохранить запись, а затем извлечь последовательность.