13. Генераторы (GENERATOR/SEQUENCE)
Генератор (generator) или последовательность (sequence) — это самый простой объект базы данных.
Он позволяет хранить целые числа в очень широком диапазоне значений: от \(-2^{63}\) до
\(2^{63}-1\).
Под него отводится 8 байтов памяти. Это подходящее средство для формирования значений искусственных первичных ключей. Для каждого искусственного первичного ключа любой таблицы базы данных пользователем создается свой собственный генератор, с которым выполняются все действия по формированию значений этого первичного ключа.
Важной особенностью генераторов является то, что работа с ними выполняется вне контекста какой-либо транзакции. Это означает, что при одновременном обращении к одному и тому же генератору разных конкурирующих транзакций никогда не возникнет конфликта блокировки, и каждый параллельный процесс получит уникальное новое числовое значение. Значение зависит от времени обращения к генератору.
В принципе, генераторы могут использоваться и для получения последовательностей неповторяющихся целых чисел для любых других целей.
13.1. Создание генератора
Для создания генератора используется оператор SQL CREATE GENERATOR/SEQUENCE.
Синтаксис оператора показан в листинге .
Листинг 13.1 Синтаксис оператора создания генератора CREATE GENERATOR/ SEQUENCE
CREATE {GENERATOR | SEQUENCE} <имя генератора>
[START WITH <начальное значение>] [INCREMENT [BY] <приращение>];
Ключевые слова GENERATOR и SEQUENCE являются синонимами (но рекомендуется использовать SEQUENCE).
Имя генератора должно быть уникальным среди имен всех генераторов базы данных и должно содержать до 63 символов.
В момент создания последовательности ей устанавливается текущее значение, указанное в необязательном предложении
START WITH минус инкремент. Если предложение START WITH отсутствует, то последовательности устанавливается
начальное значение равное 1.
Примечание
До версии 5.0 последовательности создавались с текущим значением равным стартовому значению (или 0 по умолчанию).
Следующим значением последовательности со стартовым значением 0 и приращением 1 было 1.
В версии 5.0 последовательности создаются (перезапускаются) с текущим значением равным стартовому минус инкремент. И начальным значением по умолчанию является 1 (а не 0).
То есть результат оператора NEXT VALUES FOR для последовательности со стартовым значением 100 и
приращением 10 будет 100 (а не 110, как было раньше). Аналогично функция GEN_ID(SEQ, 1)
возвратит 100 (а не 101, как было раньше).
Необязательное предложение INCREMENT [BY] позволяет задать шаг приращения (4 байтное целое число)
для оператора NEXT VALUES FOR. По умолчанию шаг приращения равен единице. Приращение не может быть
установлено в ноль для пользовательских последовательностей. Значение последовательности изменяется
также при обращении к функции GEN_ID, где в качестве параметра указывается имя последовательности
и значение приращения, которое может быть отлично от указанного в предложении INCREMENT BY.
Примечание
Создавать последовательности могут администраторы и те пользователи, у кого есть привилегия CREATE SEQUENCE (CREATE GENERATOR).
Пользователь, создавший последовательность, становится её владельцем.
CREATE SEQUENCE EMP_NO_GEN START WITH 5 INCREMENT BY 10;
13.2. Изменение значения генератора
Можно явно в любой момент времени установить новое значение генератора, выполнив
оператор SET GENERATOR (листинг ).
Листинг 13.2 Синтаксис оператора изменения значения генератора SET GENERATOR
SET GENERATOR <имя генератора> TO <значение>;
Для этой конструкции существует семантически одинаковая конструкция,
которая выполняет те же действия — ALTER SEQUENCE (см. листинг ).
Именно этот вариант рекомендуется использовать в настоящей версии Ред
База Данных.
Листинг 13.3 Альтернативный синтаксис оператора изменения значения генератора ALTER SEQUENCE
ALTER SEQUENCE <имя генератора>
[START WITH <значение>]
[RESTART [WITH <значение>]]
[INCREMENT [BY] <приращение>];
Предложение START WITH изменяет начальное значение последовательности.
Предложение RESTART WITH позволяет установить значение последовательности
(см. замечание из подраздела 13.1).
Предложение RESTART может быть использовано самостоятельно (без WITH) для перезапуска значения последовательности с начального значения или со значения,
с которого начиналась генерация при предыдущем рестарте.
Предложение INCREMENT [BY] позволяет изменить шаг приращения последовательности для оператора NEXT VALUES FOR.
Изменение значения приращения — это возможность, которая вступает в силу для каждого
запроса, который запускается после фиксаций изменения. Процедуры, которые вызваны
впервые после изменения приращения, будут использовать новое значение, если они будут
содержать операторы NEXT VALUE FOR. Процедуры, которые уже работают, не будут
затронуты, потому что они кэшируются. Процедуры, использующие NEXT VALUE FOR, не
должны быть перекомпилированы, чтобы видеть новое приращение, но если они уже работают
или загружены, то никакого эффекта не будет. Конечно процедуры, использующие GEN_ID,
не затронут при изменении приращения.
Нет особой необходимости использовать описанные операторы. Более того,
разработчиками системы не рекомендуется вообще использовать эти
операторы, поскольку это может привести к нарушениям в базе данных при
помещении в разные строки первичного ключа таблицы одинаковых значений.
Тем не менее, такие операторы были введены в SQL для большего
соответствия стандарту SQL-99. Более естественной и безопасной
конструкцией является конструкция NEXT VALUE FOR без каких-либо
неправильных модификаций значения генератора.
Когда значение генератора достигает максимальной величины, то все новые обращения к нему переводят его значение в отрицательную величину. В этот момент при каждом новом обращении к генератору начинается отрицательный отсчет от максимальной его величины (–9,223,372,036,854,775,808) к нулю.
Примечание
Операторы ALTER SEQUENCE (GENERATOR) и SET GENERATOR могут выполнять
владельцы последовательностей, администраторы и пользователи с привилегией
ALTER ANY SEQUENCE (GENERATOR).
13.3. Создание нового или изменение существующего генератора
С помощью оператора CREATE OR ALTER GENERATOR (SEQUENCE) можно создать новую или
изменить существующую последовательность:
Листинг 13.4 Синтаксис оператора CREATE OR ALTER GENERATOR /SEQUENCE
CREATE OR ALTER {GENERATOR | SEQUENCE} <имя генератора>
[{START WITH <начальное значение> | RESTART}]
[INCREMENT [BY] <приращение>];
Если последовательности не существует, то она будет создана. Уже существующая последовательность будет изменена, при этом существующие зависимости последовательности будут сохранены.
Предупреждение
Оператор CREATE OR ALTER SEQUENCE требует, чтобы хотя бы одно из необязательных предложений было указано.
13.4. Удаление генератора
Генератор можно удалить, используя оператор SQL DROP GENERATOR / SEQUENCE.
Его синтаксис представлен в листинге .
Листинг 13.5 Синтаксис оператора удаления генератора DROP GENERATOR/SEQUENCE
DROP {GENERATOR | SEQUENCE} <имя генератора>;
При наличии зависимостей для существующей последовательности (генератора) удаления не будет выполнено. Удалять генератор следует только после того, как будут удалены из базы данных все триггеры и хранимые процедуры, ссылающиеся на этот генератор.
Примечание
Удалять генераторы могут администраторы, владельцы последовательности и пользователи с
привилегией DROP ANY SEQUENCE (GENERATOR).
Практическое использование генераторов для формирования значений первичного ключа в таблицах см. в главе 12.
13.5. Пересоздание генератора
Последовательность можно пересоздать с помощью оператора RECREATE GENERATOR (SEQUENCE):
Листинг 13.6 Синтаксис оператора пересоздания генератора RECREATE GENERATOR /SEQUENCE
RECREATE {GENERATOR | SEQUENCE} <имя генератора>
[START WITH <начальное значение>] [INCREMENT [BY] <приращение>];
Если последовательность с таким именем уже существует, то оператор RECREATE SEQUENCE попытается
удалить её и создать новую последовательность. При наличии зависимостей для существующей последовательности
оператор RECREATE SEQUENCE не выполнится.
13.6. Примечание к генератору
Для генератора также можно создать примечание, используя следующий синтаксис
оператора COMMENT (см. листинг ).
Листинг 13.7 Синтаксис оператора создания примечания генератора
COMMENT ON
{GENERATOR | SEQUENCE} <имя генератора> IS {'<текст>' | NULL};
Чтобы создать примечание для генератора GEN_PEOPLE, нужно выполнить следующий оператор:
COMMENT ON
GENERATOR GEN_PEOPLE IS 'Используется для генерации первичного ключа в PEOPLE';