Работает ли PostgreSQL SERIAL по-другому?

У меня есть таблица postgres с последовательным идентификатором.

id (serial) name age

вставка обычно происходит из веб-приложения.

я вставил вручную две новые записи, установив id как max (id)+1****

после этих 2 вставить, когда веб-приложение вставляет 2 записи он дает дубликат ключа ошибка.

только для 2 записей. После этого все работает нормально.

вопрос в том, почему моя ручная вставка не увеличила серийный?

автоматический инкремент и серийный различны?

что я пропустила? У MySQL или любого другого SQL есть такая же проблема?

3 ответов


при создании serial или bigserial столбец, PostgreSQL фактически делает три вещи:

  1. создает int или .
  2. создает последовательность (принадлежащую столбцу) для создания значений для столбца.
  3. устанавливает значение столбца по умолчанию для последовательности nextval().

при вставке значения без указания serial столбец (или если вы явно указать DEFAULT как его value),nextval будет вызываться в последовательности:

  1. возвращает следующее доступное значение для столбца.
  2. увеличить значение последовательности.

если вы вручную укажите значение по умолчанию для serial столбец, то последовательность не будет обновляться и nextval может возвращать значения, что ваш serial столбец уже используется. Поэтому, если вы делаете такие вещи, вам придется вручную исправить последовательность, вызвав nextval или setval.

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

если вы используете serial или bigserial, лучше всего позволить PostgreSQL позаботиться о присвоении значений для вас и притвориться, что они являются непрозрачными числами, которые просто выходят в определенном порядке: не назначайте их сами и не предполагайте ничего о кроме уникальности. Это эмпирическое правило применяется ко всей базе данных IMO.


я не уверен, как MySQL auto_increment работает с различными типами баз данных, но, возможно,документацию поможет.


Если вы хотите вставить запись в таблицу с serial столбец-просто ommit его из запроса - он будет автоматически сгенерирован.

или вы можете вставить его значение defaul с чем-то вроде:

insert into your_table(id, val)
values (default, '123');

третий вариант-malually принимать значения из последовательной последовательности напрямую:

insert into your_table(id, val)
values (nextval(pg_get_serial_sequence('your_table','id')), '123');

я вставил вручную две новые записи, установив id как max (id)+1**

этот подход абсолютно неправильный и не будет работать в любой