Последовательности
Последовательность (sequence) — это объект в схеме базы данных, который генерирует уникальные целые числа по возрастанию или убыванию.
Последовательности обычно используются для генерации уникальных идентификаторов для строк таблицы.
Когда столбец объявлен с последовательным (serial) типом — например, SERIAL
или BIGSERIAL
— автоматически создается последовательность, которая ассоциируется с этим столбцом для генерации возрастающих значений.
Обзор
Greengage DB предоставляет следующие команды для создания, изменения и удаления последовательностей:
-
CREATE SEQUENCE
-
ALTER SEQUENCE
-
DROP SEQUENCE
Синтаксис команды CREATE SEQUENCE
описан ниже:
CREATE [ TEMP ] SEQUENCE <sequence_name>
[ INCREMENT [BY] <value> ]
[ MINVALUE <minvalue> | NO MINVALUE ]
[ MAXVALUE <maxvalue> | NO MAXVALUE ]
[ START [WITH] <start> ]
[ CACHE <cache> ]
[ [NO] CYCLE ]
[ OWNED BY { <table>.<column> | NONE } ]
Описания выражений команды CREATE SEQUENCE
:
-
CREATE SEQUENCE <sequence_name>
Создает новую последовательность с указанным именем. Имя последовательности может включать имя схемы (
<schema_name>.<sequence_name>
). -
TEMP
Если указано, объект последовательности создается только для текущей сессии.
-
INCREMENT [BY]
Указывает значение, которое добавляется к текущему значению последовательности для получения следующего. Положительное значение определяет возрастающую последовательность, отрицательное — убывающую.
-
MINVALUE <minvalue>
Указывает минимальное значение, которое может сгенерировать последовательность.
-
MAXVALUE <maxvalue>
Указывает максимальное значение для последовательности.
-
START [WITH] <start>
Указывает значение, с которого начинается последовательность.
-
CACHE <cache>
Указывает количество значений последовательности, которые будут получены и сохранены в памяти для более быстрого доступа.
-
[NO] CYCLE
Позволяет последовательности возвращаться к началу при достижении
maxvalue
(по возрастанию) илиminvalue
(по убыванию). Смотрите раздел Переполнение последовательности ниже. -
OWNED BY
Связывает последовательность со столбцом таблицы. Если этот столбец или таблица удаляются, последовательность также автоматически удаляется.
После создания последовательности можно использовать следующие функции для работы с ней:
-
nextval()
продвигает объект последовательности к следующему значению и возвращает это значение. Смотрите раздел Получение нового значения последовательности ниже. -
setval()
устанавливает текущее значение объекта последовательности и, опционально, флагis_called
. Смотрите раздел Установка текущего значения последовательности ниже.
Функции PostgreSQL currval()
и lastval()
для работы с последовательностями не поддерживаются в Greengage DB.
Создание последовательности
Команда CREATE SEQUENCE
ниже создает последовательность с указанным именем и начальным значением:
CREATE SEQUENCE customer_id_seq START 101;
Последовательность customer_id_seq
начинается с 101
и по умолчанию увеличивается на 1
, генерируя уникальные числовые значения при каждом вызове.
Использование последовательностей в DML-командах
Получение нового значения последовательности
В этом разделе показано, как использовать функцию nextval()
для генерации уникальных идентификаторов для строк таблицы.
Функция принимает имя последовательности в качестве аргумента.
Создайте таблицу:
CREATE TABLE customers
(
customer_id BIGINT,
name TEXT,
email TEXT
)
WITH (appendoptimized = true)
DISTRIBUTED BY (customer_id);
Для вставки данных используйте команду INSERT INTO
.
Для генерации значений идентификатора клиента в функцию nextval()
передается имя последовательности:
INSERT INTO customers (customer_id, name, email)
VALUES (nextval('customer_id_seq'), 'Andrew Fuller', 'andrew@example.com'),
(nextval('customer_id_seq'), 'Michael Suyama', 'michael@testmail.com'),
(nextval('customer_id_seq'), 'Laura Callahan', 'laura@example.io'),
(nextval('customer_id_seq'), 'Nancy Davolio', 'nancy@samplemail.com'),
(nextval('customer_id_seq'), 'Steven Buchanan', 'steven@fastmail.net');
Используйте команду SELECT
, чтобы проверить данные, добавленные в таблицу:
SELECT *
FROM customers
ORDER BY customer_id;
Вывод показывает, что у каждого клиента есть уникальный ID начиная с 101
:
customer_id | name | email -------------+-----------------+---------------------- 101 | Laura Callahan | laura@example.io 102 | Nancy Davolio | nancy@samplemail.com 103 | Michael Suyama | michael@testmail.com 104 | Andrew Fuller | andrew@example.com 105 | Steven Buchanan | steven@fastmail.net (5 rows)
nextval() и откат транзакций
Операция nextval()
никогда не откатывается.
Как только значение получено, оно считается использованным — даже если транзакция, вызвавшая nextval()
, завершилась неудачно.
В результате неудачные транзакции могут приводить к пропускам в последовательности назначаемых значений.
Следующий запрос пытается вставить новую запись о клиенте, но затем откатывает транзакцию, отменяя операцию INSERT
:
BEGIN;
INSERT INTO customers (customer_id, name, email)
VALUES (nextval('customer_id_seq'), 'Margaret Peacock', 'margaret@example.com');
ROLLBACK;
Используйте SELECT nextval()
, чтобы проверить текущее значение последовательности:
SELECT nextval('customer_id_seq');
Возвращаемое значение должно быть 107
, что указывает на то, что последовательность увеличивается, даже если операция INSERT
была отменена:
nextval --------- 107
Установка текущего значения последовательности
Вы можете использовать функцию setval()
для установки текущего значения последовательности.
Эта функция также принимает необязательный параметр is_called
.
Если этот параметр установлен в true
(по умолчанию), следующий вызов nextval()
продвинет последовательность, прежде чем вернуть значение.
Если is_called
— false
, nextval()
вернет последнее значение.
Следующая команда устанавливает текущее значение последовательности customer_id_seq
в 200
:
SELECT setval('customer_id_seq', 200);
Чтобы вставить новую строку в таблицу, используйте команду INSERT INTO
:
INSERT INTO customers (customer_id, name, email)
VALUES (nextval('customer_id_seq'), 'Margaret Peacock', 'margaret@example.com');
Затем получите данные из таблицы customers
:
SELECT *
FROM customers
ORDER BY customer_id;
Результат должен показать, что customer_id
для новой строки равен 201
:
customer_id | name | email -------------+------------------+---------------------- 101 | Laura Callahan | laura@example.io 102 | Nancy Davolio | nancy@samplemail.com 103 | Michael Suyama | michael@testmail.com 104 | Andrew Fuller | andrew@example.com 105 | Steven Buchanan | steven@fastmail.net 201 | Margaret Peacock | margaret@example.com
Переполнение последовательности
По умолчанию последовательность не перезапускается после достижения максимального/минимального значения.
Когда достигается максимальное или минимальное значение (предел типа данных или значение параметра <maxvalue>
/<minvalue>
), любой вызов nextval()
приводит к ошибке.
Чтобы разрешить последовательности возвращаться к значению, заданному выражением START [WITH]
, используйте параметр CYCLE
.
Создайте новую последовательность с MAXVALUE
, установленным в 5
:
CREATE SEQUENCE customer_id_seq_small MAXVALUE 5;
Создайте таблицу:
CREATE TABLE customers_with_small_sequence
(
customer_id BIGINT,
name TEXT,
email TEXT
)
WITH (appendoptimized = true)
DISTRIBUTED BY (customer_id);
Вставьте пять значений в таблицу:
INSERT INTO customers_with_small_sequence (customer_id, name, email)
VALUES (nextval('customer_id_seq_small'), 'Andrew Fuller', 'andrew@example.com'),
(nextval('customer_id_seq_small'), 'Michael Suyama', 'michael@testmail.com'),
(nextval('customer_id_seq_small'), 'Laura Callahan', 'laura@example.io'),
(nextval('customer_id_seq_small'), 'Nancy Davolio', 'nancy@samplemail.com'),
(nextval('customer_id_seq_small'), 'Steven Buchanan', 'steven@fastmail.net');
Затем попробуйте вставить новое значение:
INSERT INTO customers_with_small_sequence (customer_id, name, email)
VALUES (nextval('customer_id_seq_small'), 'Margaret Peacock', 'margaret@example.com');
Возвращается следующая ошибка:
ERROR: nextval: reached maximum value of sequence "customer_id_seq_small" (5)
Чтобы разрешить последовательности переходить к начальному значению при достижении максимального, включите опцию CYCLE
, используя команду ALTER SEQUENCE
:
ALTER SEQUENCE customer_id_seq_small CYCLE;
Запрос INSERT
должен выполняться без ошибок:
INSERT INTO customers_with_small_sequence (customer_id, name, email)
VALUES (nextval('customer_id_seq_small'), 'Margaret Peacock', 'margaret@example.com');
Получите данные из таблицы customers_with_small_sequence
:
SELECT *
FROM customers_with_small_sequence
ORDER BY customer_id;
Результат показывает, что существует два клиента с ID, равным 1
:
customer_id | name | email -------------+------------------+---------------------- 1 | Margaret Peacock | margaret@example.com 1 | Andrew Fuller | andrew@example.com 2 | Michael Suyama | michael@testmail.com 3 | Steven Buchanan | steven@fastmail.net 4 | Nancy Davolio | nancy@samplemail.com 5 | Laura Callahan | laura@example.io (6 rows)
Использование последовательностей в определении таблицы
Значение столбца по умолчанию
Вы можете использовать последовательность в команде CREATE TABLE
, например:
CREATE TABLE customers_with_sequence
(
customer_id BIGINT DEFAULT nextval('customer_id_seq'),
name TEXT,
email TEXT
)
WITH (appendoptimized = true)
DISTRIBUTED BY (customer_id);
Если вы вставляете строки без указания значений customer_id
, Greengage DB автоматически получает следующее значение из последовательности customer_id_seq
:
INSERT INTO customers_with_sequence (name, email)
VALUES ('Andrew Fuller', 'andrew@example.com'),
('Michael Suyama', 'michael@testmail.com'),
('Laura Callahan', 'laura@example.io'),
('Nancy Davolio', 'nancy@samplemail.com'),
('Steven Buchanan', 'steven@fastmail.net');
Получите данные из таблицы:
SELECT *
FROM customers_with_sequence
ORDER BY customer_id;
Результат должен выглядеть так:
customer_id | name | email -------------+-----------------+---------------------- 202 | Andrew Fuller | andrew@example.com 203 | Michael Suyama | michael@testmail.com 204 | Laura Callahan | laura@example.io 205 | Nancy Davolio | nancy@samplemail.com 206 | Steven Buchanan | steven@fastmail.net (5 rows)
Последовательные типы
Объявление столбца последовательного типа (SMALLSERIAL
, SERIAL
или BIGSERIAL
) неявно создает последовательность для использования в этом столбце таблицы.
Последовательность получает имя по шаблону <table_name>_<column_name>_seq
и может использоваться в DML-командах так же, как и любая последовательность, созданная вручную.
Вы можете узнать больше о последовательных типах в соответствующем разделе документации PostgreSQL: Serial Types.
В приведенном ниже примере столбец customer_id
имеет тип SERIAL
:
CREATE TABLE customers_with_serial
(
customer_id SERIAL,
name TEXT,
email TEXT
)
WITH (appendoptimized = true)
DISTRIBUTED BY (customer_id);
При вставке строк Greengage DB автоматически получает следующее значение из неявно созданной последовательности:
INSERT INTO customers_with_serial (name, email)
VALUES ('Andrew Fuller', 'andrew@example.com'),
('Michael Suyama', 'michael@testmail.com'),
('Laura Callahan', 'laura@example.io'),
('Nancy Davolio', 'nancy@samplemail.com'),
('Steven Buchanan', 'steven@fastmail.net');
Получите данные из таблицы:
SELECT *
FROM customers_with_serial
ORDER BY customer_id;
Результат должен выглядеть так:
customer_id | name | email -------------+-----------------+---------------------- 1 | Andrew Fuller | andrew@example.com 2 | Michael Suyama | michael@testmail.com 3 | Laura Callahan | laura@example.io 4 | Nancy Davolio | nancy@samplemail.com 5 | Steven Buchanan | steven@fastmail.net
Изменение последовательностей
Команда ALTER SEQUENCE
изменяет атрибуты существующей последовательности.
Чтобы перезапустить последовательность customer_id_seq
начиная с 1001
, используйте команду:
ALTER SEQUENCE customer_id_seq RESTART WITH 1001;
Свяжите последовательность с определенным столбцом таблицы:
ALTER SEQUENCE customer_id_seq OWNED BY customers.customer_id;
Добавьте новые данные в таблицу customers
:
INSERT INTO customers (customer_id, name, email)
VALUES (nextval('customer_id_seq'), 'Robert King', 'robert@demo.org'),
(nextval('customer_id_seq'), 'Janet Leverling', 'janet@businessmail.com');
Затем получите данные из таблицы:
SELECT *
FROM customers
ORDER BY customer_id;
Результат показывает, что идентификаторы новых клиентов начинаются с 1001
:
customer_id | name | email -------------+------------------+------------------------ 101 | Laura Callahan | laura@example.io 102 | Nancy Davolio | nancy@samplemail.com 103 | Michael Suyama | michael@testmail.com 104 | Andrew Fuller | andrew@example.com 105 | Steven Buchanan | steven@fastmail.net 201 | Margaret Peacock | margaret@example.com 1001 | Robert King | robert@demo.org 1002 | Janet Leverling | janet@businessmail.com (8 rows)
Просмотр информации о последовательностях
В этом разделе показано, как получить информацию о последовательностях.
-
Чтобы получить информацию о последовательности, используйте команду
SELECT
:SELECT * FROM customer_id_seq;
Результат включает параметры последовательности, такие как ее начальное значение, минимальное и максимальное значения:
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called -----------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+----------- customer_id_seq | 1002 | 101 | 1 | 9223372036854775807 | 1 | 1 | 31 | f | t
-
Чтобы получить список всех последовательностей, используйте метакоманду
psql
\ds
:\ds
Результат выглядит следующим образом:
List of relations Schema | Name | Type | Owner --------+---------------------------------------+----------+--------- public | customer_id_seq | sequence | gpadmin public | customer_id_seq_small | sequence | gpadmin public | customers_with_serial_customer_id_seq | sequence | gpadmin
Результат включает автоматически созданную последовательность
customers_with_serial_customer_id_seq
для столбцаcustomer_id
с типомSERIAL
. -
Вы можете получить информацию о последовательностях из представления
information_schema.sequences
: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 | customer_id_seq | bigint | 1 | 9223372036854775807 | 1 | NO public | customer_id_seq_small | bigint | 1 | 5 | 1 | YES public | customers_with_serial_customer_id_seq | bigint | 1 | 9223372036854775807 | 1 | NO
Удаление последовательностей
Чтобы удалить последовательность, используйте команду DROP SEQUENCE
:
DROP SEQUENCE customer_id_seq_small;
Чтобы удалить последовательность вместе со связанными объектами, например, таблицами, которые ее используют, используйте параметр CASCADE
:
DROP SEQUENCE customer_id_seq CASCADE;