Генерация идентификаторов

Всем добрый день.
Возникла необходимость создания таблицы, в которой одна колонка играла бы роль первичного ключа и заполнялась автоматически.
Немного погуглив, я наткнулся на решение с использованием SEQUENCE

CREATE SEQUENCE testseq MINVALUE 1 MAXVALUE 5 CYCLE;

После создаю таблицу

CREATE TABLE foo (
    id integer NOT NULL DEFAULT NEXTVAL('testseq'),
    name text,
    PRIMARY KEY (id)
 );

Добавляю в нее значения

INSERT INTO foo (name) VALUES('A');
INSERT INTO foo (name) VALUES('B');
INSERT INTO foo (name) VALUES('C');
INSERT INTO foo (name) VALUES('D');
INSERT INTO foo (name) VALUES('E');
SELECT * FROM foo;

И получаю
id | name
----+------
1 | A
2 | B
3 | C
4 | D
5 | E
(5 rows)

Далее удаляю 3 строку

DELETE FROM foo WHERE id='3';

И пытаюсь добавить одну строку
INSERT INTO foo (name) VALUES('test');

Получаю
ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "foo_pke
y"
DETAIL: Ключ "(id)=(1)" уже существует.

Это впринципе логично, но как заставить SEQUENCE перебирать допустимые значения, пока не встретится незанятое?

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Вам нужен тип SERIAL вместо

Вам нужен тип SERIAL вместо SEQUENCE

А точно будет это работать

А точно будет это работать как надо?
Вот что написано в официальной доке
8.1.4. Serial Types

The data types serial and bigserial are not true types, but merely a notational convenience for setting up unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying

CREATE TABLE tablename (
    colname SERIAL
);

is equivalent to specifying:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer DEFAULT NEXTVAL('tablename_colname_seq') NOT NULL
);

Тем более хотелось бы ограничить пределы изменения чисел в колонке id, например, шестизначными числами

Счётчик SERIAL зациклен по

Счётчик SERIAL зациклен по кругу, т.е. следующее значение берётся как максимальное + 1 до тех пор пока не достигнет максимально допустимого значения для данного типа данных. По достижении происходит сброс в 0 и снова по кругу.

Если вам нужны тонкости - делайте триггерную систему. Поясню.
При вставке новой записи срабатывает триггер, по которому происходит просмотр некоей таблице свободных номеров (предположит называется free_number) Если таблица пуста, то следующий номер берётся как max(ID)+1, если таблица не пуста, берётся наименьший свободный номер из неё, после чего этот номер из free_number удаляется.
При удалении записи снова срабатывает триггер (уже другой), который перед удалением записи берёт её ID и помещает в таблицу free_number.
Вот собственно и всё.

Спасибо. Наверное буду делать

Спасибо. Наверное буду делать триггерную систему.

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Back to top

(С) Виктор Вислобоков, 2008-2023