Работает ли 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**
этот подход абсолютно неправильный и не будет работать в любой