Функции nextval и currval
В этой статье рассматриваются функции для работы с последовательностями в рамках одной транзакции, когда в первом запросе добавляется запись в таблицу в базе данных, а в последующих запросах используется ее идентификатор.
Функция nextval
Функция nextval
продвигает последовательность к следующему значению и возвращает его. Это атомарная операция: если nextval
вызывается одновременно в нескольких сеансах, в результате каждого вызова будут гарантированно получены разные значения.
Как правило вызов этой функции указывается в качестве дефолтного значения для первичного ключа. Например, таблица пользователей:
Во избежание блокирования параллельных транзакций, пытающихся получить значения одной последовательности, операция nextval
никогда не откатывается; то есть, как только значение было выбрано, оно считается использованным и не будет возвращено снова. Это утверждение верно, даже когда окружающая транзакция впоследствии прерывается или вызывающий запрос никак не использует это значение.
Если в качестве типа колонки используется serial или bigserial, то такие типы автоматически создают последовательности и неявным образом вызывают nextval,
если при добавлении записи в таблицу полю не задали конкретное значение.
Функция currval
Возвращает значение, выданное при последнем вызове nextval
для этой последовательности в текущем сеансе. Если в данном сеансе nextval
ни разу не вызывалась (явно или неявно) для данной последовательности, возвращается ошибка. Так как это значение ограничено рамками сеанса, эта функция выдаёт предсказуемый результат вне зависимости от того, вызвалась ли впоследствии nextval
в других сеансах или нет.
Рассмотрим использования currval
на примере добавления нового пользователя:
Так как nextval
указан в качестве дефолтного значения для колонки user_id таблицы public.user и в запросе не указывается конкретное значение, то при выполнении команды INSERT
она сработает автоматически, что позволяет использовать currval
в следующей команде INSERT
.
Значение last_value
Последовательность хранит свое значение во внутренней таблице. Получить это значение можно через last_value и SELECT-запрос:
Преимущество такого способа в том, что для получения значения не нужно вызывать nextval
в том же сеансе. Но значение last_value не является потокобезопасным. Если last_value будет вызываться в нескольких сеансах одновременно, то во всех сеансах будет использоваться одно и тоже значение, что может нарушить целостность данных.
Last updated