Постановка задачи
В вашем случае кажется, что проблема, с которой вы столкнулись, заключается в том, что вы сделали следующее:
- Экспортированные данные, которые уже имеют серийный номер
- Импортировал экспорт в базу данных Postgres
- Пытался вставить дополнительные данные, обнаружив, что серийный номер либо:
а) возник конфликт, поскольку он попытался вставить дубликат существующего серийного номера; или
б) успешно вставлен дубликат существующего серийного номера
Справочная информация о сериалах в Postgres
В PostgreSQL тип данных serial
действительно сокращен для столбца integer
со связанным sequence
, который управляет поведением столбца по умолчанию.
Из документации :
Типы данных smallserial, serial и bigserial не являются истинными типами, а являются просто условным обозначением для создания столбцов уникальных идентификаторов (аналогично свойству AUTO_INCREMENT, поддерживаемому некоторыми другими базами данных).
Вы можете проверить это поведение, проверив значение по умолчанию для столбца (например, используя \d+
в psql). Столбец Default
должен выглядеть примерно так: nextval('schema.id_seq'::regclass)
. Из документации стоит отметить, что:
В большинстве случаев вы также хотели бы присоединить ограничение UNIQUE или PRIMARY KEY, чтобы предотвратить случайное добавление повторяющихся значений, но это не происходит автоматически.
В качестве примечания важно отметить, что последовательности не обещают, что значения будут последовательными .
Решение
Причина, по которой возможно оказаться в описанной вами ситуации, заключается в том, что последовательность, генерирующая новые значения, вызывается только в том случае, если значение явно не указано.
Когда вы думаете о serial
s как о целых числах и значениях по умолчанию, это начинает иметь смысл Postgres отслеживает, какое значение следует использовать следующим, через последовательность, а назначает новые значения из последовательности только в том случае, если вы явно не указали значение.
Способ решить эту проблему - установить nextval
с помощью функции setval
в Postgres. Есть много разных стратегий, как именно это сделать, в зависимости от того, хотите ли вы:
- Сброс всех серийных номеров
- Сохранить все существующие серийные номера и начать со следующего значения
- Другое, нестандартное решение
Вот ответ на связанный вопрос о том, как установить последовательность для определенного значения.
Тривиальный пример
В приведенном ниже примере показано, как при предоставлении явного значения для вставки / выгрузки не используется значение по умолчанию / последовательность, и как следующая вставка, которая будет выполняться, продолжится по существующей последовательности.
CREATE TABLE test (id serial, sample integer);
INSERT INTO test (sample) VALUES (101); -- assigns default, next value from id_seq (1)
INSERT INTO test (id, sample) VALUES (3, 102); -- assigns explicit value (3)
INSERT INTO test (sample) VALUES (103); -- assigns default, next value from id_seq (2)