Работает ли PostgreSQL SERIAL по-другому?
У меня есть таблица postgres с последовательным идентификатором.
id (serial) name age
вставка обычно происходит из веб-приложения.
я вставил вручную две новые записи, установив id как max (id)+1****
после этих 2 вставить, когда веб-приложение вставляет 2 записи он дает дубликат ключа ошибка.
только для 2 записей. После этого все работает нормально.
вопрос в том, почему моя ручная вставка не увеличила серийный?
автоматический инкремент и серийный различны?
что я пропустила? У MySQL или любого другого SQL есть такая же проблема?
3 ответов
при создании serial
или bigserial
столбец, PostgreSQL фактически делает три вещи:
- создает
int
или . - создает последовательность (принадлежащую столбцу) для создания значений для столбца.
- устанавливает значение столбца по умолчанию для последовательности
nextval()
.
при вставке значения без указания serial
столбец (или если вы явно указать DEFAULT
как его value),nextval
будет вызываться в последовательности:
- возвращает следующее доступное значение для столбца.
- увеличить значение последовательности.
если вы вручную укажите значение по умолчанию для 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**
этот подход абсолютно неправильный и не будет работать в любой