Последовательности
Последовательность — это объект, относящийся к определенной схеме, который генерирует ряд уникальных целых чисел в порядке возрастания или убывания. Последовательность не связана ни с какой таблицей, но её можно использовать для заполнения данных в первичном ключе или уникальных столбцах таблицы. Типы PostgreSQL serial представляют собой последовательности.
Создание последовательности
Чтобы создать последовательность, выполните команду CREATE SEQUENCE
, которая создает новый генератор последовательности.
CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] <имя>
[ AS <тип_данных> ]
[ INCREMENT [ BY ] <инкремент> ]
[ MINVALUE <мин_значение> | NO MINVALUE ] [ MAXVALUE <макс_значение> | NO MAXVALUE ]
[ START [ WITH ] <начало> ] [ CACHE <размер_кеша> ] [ [ NO ] CYCLE ]
[ OWNED BY { <имя_таблицы.имя_столбца> | NONE } ]
TEMPORARY | TEMP |
Если указано, объект последовательности создается только для текущей сессии. Временная последовательность удаляется в конце сессии. Существующие постоянные последовательности с тем же именем не отображаются в текущей сессии, пока существует временная последовательность. Чтобы обратиться к постоянной последовательности, необходимо дополнить имя указанием схемы |
IF NOT EXISTS |
PostgreSQL создает последовательность, если отношения с таким именем не существует. Если указан этот параметр и в базе данных имеется отношение с указанным именем, PostgreSQL не выдает ошибку. Не гарантируется, что существующее отношение соответствует тому, которое могло быть создано |
<имя> |
Имя новой последовательности. Может включать имя схемы ( |
<тип_данных> |
Необязательное выражение |
<инкремент> |
Необязательное выражение |
MINVALUE <мин_значение> | NO MINVALUE |
Необязательное выражение |
MAXVALUE <макс_значение> | NO MAXVALUE |
Необязательное выражение |
<начало> |
Необязательное выражение |
<размер_кеша> |
Необязательное выражение |
[ NO ] CYCLE |
Опция Если указано необязательное ключевое слово |
OWNED BY <имя_таблицы.имя_столбца> | NONE |
Выражение |
В следующем примере создается последовательность, начинающаяся с 2
.
CREATE SEQUENCE mysequence START 2;
CREATE SEQUENCE
создает и инициализирует новую специальную однострочную таблицу с указанным именем. Пользователь, выполняющий CREATE SEQUENCE
, становится владельцем последовательности.
Если указано имя схемы, последовательность создается в этой схеме. В противном случае она создается в текущей схеме. Временные последовательности существуют в специальной схеме, поэтому при создании временной последовательности нельзя указать имя схемы.
Последовательности основаны на арифметике bigint
, поэтому диапазон не может превышать диапазон восьмибайтового целого числа (от -9223372036854775808 до 9223372036854775807).
Чтобы проверить текущее состояние последовательности, используйте SELECT
.
SELECT * FROM mysequence;
Результат:
last_value | log_cnt | is_called ------------+---------+----------- 2 | 0 | f
Поле last_value
последовательности показывает последнее значение, сгенерированное для любой сессии. Это значение может устареть к моменту его печати, если другие сессии активно выполняют вызовы nextval
.
PostgreSQL не логирует (не записывает в WAL) каждую полученную выборку из последовательности по соображениям производительности, он заранее записывает несколько выборок. В случае сбоя PostgreSQL теряет (пропускает) столько выборок, сколько было предварительно записано. log_cnt
показывает, сколько выборок осталось до того, как необходимо будет создать новую запись WAL.
Если поле is_called
имеет значение t
— true
, следующий вызов nextval
продвинет последовательность перед возвратом значения. Если is_called
имеет значение f
— false
, nextval
вернет значение last_value
.
После создания последовательности используйте функции манипулирования последовательностью для работы с ней. См. Работа с последовательностями.
CREATE SEQUENCE
соответствует стандарту SQL со следующими исключениями:
-
Необходимо использовать функцию
nextval
вместо стандартного выраженияNEXT VALUE FOR
. -
Выражение
OWNED BY
является расширением PostgreSQL.
Изменение последовательности
Используйте ALTER SEQUENCE
, чтобы изменить определение генератора последовательности. Любые параметры, которые не заданы с помощью команды ALTER SEQUENCE
, сохраняют свои предыдущие значения.
Вы должны быть владельцем последовательности, чтобы использовать ALTER SEQUENCE
. У вас также должно быть право CREATE
для новой схемы, чтобы изменить схему последовательности. Для изменения владельца вы должны быть прямым или косвенным членом новой роли владельца, и эта роль должна иметь привилегию CREATE
в схеме последовательности.
ALTER SEQUENCE [ IF EXISTS ] <имя>
[ AS <тип_данных> ]
[ INCREMENT [ BY ] <инкремент> ]
[ MINVALUE <мин_значение> | NO MINVALUE ] [ MAXVALUE <макс_значение> | NO MAXVALUE ]
[ START [ WITH ] <начало> ]
[ RESTART [ [ WITH ] <перезапуск> ] ]
[ CACHE <размер_кеша> ] [ [ NO ] CYCLE ]
[ OWNED BY { <имя_таблицы.имя_столбца> | NONE } ]
ALTER SEQUENCE [ IF EXISTS ] <имя> OWNER TO { <новый_владелец> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER SEQUENCE [ IF EXISTS ] <имя> RENAME TO <новое_имя>
ALTER SEQUENCE [ IF EXISTS ] <имя> SET SCHEMA <новая_схема>
<имя> |
Имя последовательности, подлежащей изменению. Может включать имя схемы ( |
IF EXISTS |
Когда указана эта опция, PostgreSQL не выдает ошибку, если последовательности с указанным именем не существует в базе данных. В этом случае отображается уведомление |
<тип_данных> |
Необязательное выражение |
<инкремент> |
Необязательное выражение |
MINVALUE <мин_значение> | NO MINVALUE |
Необязательное выражение |
MAXVALUE <макс_значение> | NO MAXVALUE |
Необязательное выражение |
<начало> |
Необязательное выражение |
<перезапуск> |
Необязательное выражение |
<размер_кеша> |
Необязательное выражение |
[ NO ] CYCLE |
Опция Если указано необязательное ключевое слово |
OWNED BY <имя_таблицы.имя_столбца> | NONE |
Выражение |
<новый_владелец> |
Имя пользователя, назначаемого новым владельцем последовательности |
<новое_имя> |
Новое имя последовательности |
<новая_схема> |
Новая схема последовательности |
Следующий пример делает последовательность mysequence
убывающей от 10
до 2
с использованием шага 2
и зацикливает последовательность:
ALTER SEQUENCE mysequence
INCREMENT -2
MINVALUE 2
MAXVALUE 10
RESTART 10
CYCLE;
ALTER SEQUENCE
не оказывает немедленного влияния на результаты nextval
в серверных процессах, которые имеют кешированные значения последовательности. Они получат изменения только после того, как будут использованы все кешированные значения. Текущий серверный процесс сразу реагирует на изменения.
ALTER SEQUENCE
не влияет на значение currval
последовательности.
ALTER SEQUENCE
блокирует одновременные вызовы nextval
, currval
, lastval
и setval
.
По историческим причинам ALTER TABLE
тоже может работать с последовательностями, но допустимы только разновидности ALTER TABLE
, равнозначные вышеперечисленным формам.
Удаление последовательности
Команда DROP SEQUENCE
удаляет последовательность. Эту операцию может осуществить только владелец последовательности или суперпользователь.
DROP SEQUENCE [ IF EXISTS ] <имя> [, ...] [ CASCADE | RESTRICT ]
IF EXISTS |
Когда указана эта опция, PostgreSQL не выдает ошибку, если последовательности с указанным именем не существует в базе данных. В этом случае отображается уведомление |
<имя> [, …] |
Имя последовательности, подлежащей удалению. Может включать имя схемы ( |
CASCADE |
Удалять объекты, зависящие от данной последовательности, и, в свою очередь, все объекты, зависящие от этих объектов. См. Dependency Tracking |
RESTRICT |
Отказаться от удаления последовательности, если от нее зависят какие-либо объекты. Это поведение по умолчанию |
Пример:
DROP SEQUENCE mysequence;
Работа с последовательностями
Функции, описанные ниже, предоставляют простые и безопасные при параллельном использовании методы получения значений последовательностей.
nextval
Функция nextval
продвигает объект последовательности к следующему значению и возвращает это значение.
nextval ( <regclass> ) -> bigint
Если несколько сессий одновременно выполняют nextval
, каждая безопасно получает отдельное значение последовательности. Если объект последовательности был создан с параметрами по умолчанию, вызовы nextval
будут возвращать последовательные значения, начиная с 1
. Другие варианты поведения можно указать, используя соответствующие параметры в команде CREATE SEQUENCE.
Функция nextval
требует привилегий USAGE
или UPDATE
для последовательности.
В примере ниже показано, как создать последовательность, связанную со столбцом таблицы, и заполнить столбец с помощью nextval
. Для этого необходимо выполнить следующие действия:
-
Создайте таблицу.
CREATE TABLE book_orders ( order_id SERIAL, item_id INT NOT NULL, book_name VARCHAR NOT NULL, price NUMERIC NOT NULL, PRIMARY KEY(order_id, item_id) );
-
Создайте новую последовательность, связанную со столбцом
item_id
таблицыbook_orders
.CREATE SEQUENCE book_order_items START 1 OWNED BY book_orders.item_id;
-
Добавьте строки в таблицу, используя функцию
nextval
для заполнения столбцаitem_id
.INSERT INTO book_orders(order_id, item_id, book_name, price) VALUES (1, nextval('book_order_items'),'Hyperion',21), (1, nextval('book_order_items'),'War and Peace',26), (2, nextval('book_order_items'),'1984',20), (2, nextval('book_order_items'),'The Time Machine',19);
-
Проверьте данные таблицы.
SELECT * FROM book_orders;
Результат:
order_id | item_id | book_name | price ----------+---------+------------------+------- 1 | 1 | Hyperion | 21 1 | 2 | War and Peace | 26 2 | 3 | 1984 | 20 2 | 4 | The Time Machine | 19
Если вы удалите таблицу book_orders
, последовательность book_order_items
также будет удалена.
setval
Функция setval
устанавливает текущее значение объекта последовательности, а также флаг is_called
. setval
может вызываться с двумя или тремя параметрами.
setval ( <regclass>, <bigint> [, <boolean> ] ) -> bigint
Где:
-
<regclass>
— имя последовательности; -
<bigint>
— значениеlast_value
; -
<boolean>
— значениеis_called
.
Форма с двумя параметрами присваивает полю last_value
указанное значение (<bigint>
), а для поля is_called
устанавливает значение true
, что означает, что следующий вызов nextval
продвигает последовательность перед возвращением значения. Функция currval
также будет возвращать указанное значение. Если setval
вызывается с тремя параметрами, для is_called
может быть установлено значение true
или false
. true
будет иметь тот же эффект, что и вызов функции с двумя параметрами. Если для is_called
установлено значение false
, следующий вызов nextval
вернет указанное значение. Функция currval
также будет возвращать это значение. В таблице ниже приведены примеры setval
и их результаты.
Команда | Значение, которое вернет nextval |
---|---|
SELECT setval('mysequence', 14); |
15 |
SELECT setval('mysequence', 14, true); |
15 |
SELECT setval('mysequence', 14, false); |
14 |
Результат, возвращаемый setval
, является значением второго параметра.
Функция setval
требует привилегии UPDATE
для последовательности.
currval
Функция currval
возвращает последнее значение, полученное с помощью nextval
, для указанной последовательности в текущей сессии.
currval ( <regclass> ) -> bigint
Если nextval
не вызывался для этой последовательности в текущей сессии и вы пытаетесь выполнить currval
, возникнет ошибка. Поскольку currval
возвращает значение для текущей сессии, она дает предсказуемый результат независимо от того, вызывается ли nextval
в других сессиях.
Функция currval
требует привилегий USAGE
или SELECT
для последовательности.
Пример:
SELECT currval('mysequence');
Результат:
currval --------- 14 (1 row)
lastval
Функция возвращает последнее полученное значение с помощью nextval
в текущей сессии для любой последовательности.
lastval () -> bigint
Эта функция идентична currval
, но вместо того, чтобы принимать имя последовательности в качестве аргумента, она ссылается на последний вызов nextval
, относящийся к любой последовательности в текущей сессии. Если nextval
не вызывалась в текущей сессии и вы пытаетесь выполнить lastval
, возникнет ошибка.
Функция lastval
требует привилегий USAGE
или SELECT
для последовательности.
Пример:
SELECT * FROM lastval();
Результат:
lastval --------- 14 (1 row)
Получение информации о последовательностях
Вы можете получить информацию о последовательностях из представления sequences, хранящегося в схеме information_schema
.
SELECT sequence_schema, sequence_name, data_type, minimum_value, maximum_value, increment, cycle_option
FROM information_schema.sequences;
Результат:
sequence_schema | sequence_name | data_type | minimum_value | maximum_value | increment | cycle_option -----------------+--------------------------+-----------+---------------+---------------------+-----------+-------------- public | mysequence | bigint | 2 | 10 | -2 | YES public | book_orders_order_id_seq | integer | 1 | 2147483647 | 1 | NO public | book_order_items | bigint | 1 | 9223372036854775807 | 1 | NO (3 rows)
Результат включает автоматически сгенерированную последовательность book_orders_order_id_seq
для столбца order_id
типа serial.
Представление pg_sequences также обеспечивает доступ к полезной информации о каждой последовательности в базе данных. Например, вы можете получить информацию о владельцах последовательностей, которой нет в information_schema.sequences
:
SELECT sequencename, sequenceowner FROM pg_sequences;
Результат:
sequencename | sequenceowner --------------------------+--------------- mysequence | postgres book_orders_order_id_seq | postgres book_order_items | postgres
Кроме того, вы также можете получить данные из системных каталогов pg_sequence и pg_class, используя следующий запрос:
SELECT pg_class.relname, pg_sequence.* FROM pg_sequence INNER JOIN pg_class ON pg_sequence.seqrelid = pg_class.oid;
Результат:
relname |seqrelid|seqtypid|seqstart|seqincrement| seqmax |seqmin|seqcache| seqcycle ------------------------+--------+--------+--------+------------+-------------------+------+--------+---------- mysequence | 157170 | 20 | 2 | -2 | 10| 2 | 1 | t book_orders_order_id_seq| 160111 | 23 | 1 | 1 | 2147483647| 1 | 1 | f book_order_items | 160126 | 20 | 1 | 1 |9223372036854775807| 1 | 1 | f (3 rows)
Также можно использовать метакоманду psql
\ds
для вывода списка последовательностей, созданных в текущей базе данных.
\ds
Результат:
List of relations Schema | Name | Type | Owner --------+--------------------------+----------+---------- public | book_order_items | sequence | postgres public | book_orders_order_id_seq | sequence | postgres public | mysequence | sequence | postgres (3 rows)