Почему PostgreSQL не увеличивает last_value для id_sequence при объединении экземпляра?

1

В предыдущем вопросе я задавался вопросом, почему я получал ошибку целостности от SA при объединении экземпляра с идентификатором в первый раз в базу данных (ввод данных привязки).

Тем не менее, я научился учитывать проблему, позвонив с самым высоким индексом, который я вводил:

select setval('my_items_id_seq', {id});

Однако это не решило основной проблемы, с которой я сейчас борюсь. Почему не сливается вызов nextval() в последовательности при вставке новой строки?

Теги:
sqlalchemy

2 ответа

3
Лучший ответ

Если ваш объект уже имеет свой набор атрибутов PK, то идентификационная последовательность не будет использоваться и, следовательно, не будет увеличиваться, потому что нет никакой причины, чтобы база данных выполняла неявную insert into mytable (id,...) values ((select nextval from mytable_id_seq),...).

Вы уверены, что вам нужно делать merge вместо add на свою session? Если вы действительно вставляете, я бы подумал, что это скорее операция add. Если вы просто повторно используете объект, который все еще находится в памяти, но добавлен ранее и, возможно, теперь изменен в базе данных, то merge является подходящим.

  • 0
    Wberry это правильно. Вы используете слияние только для ввода отключенных объектов или объектов из другого сеанса. Если это new объект, который вы создали, то вам нужно использовать add . Имейте в виду, что использование setval использованию текущего значения последовательности независимо от того, какие идентификаторы могут уже существовать в вашей таблице - если вы не очистили данные таблицы до добавления новых объектов, вы можете получить ошибки перекрытия ключей и целостности.
0

Я боролся с той же проблемой IntegrityErrors в PostgreSQL, пока не нашел этот пост. Я решил придерживаться следующего правила: если объект не существует в базе данных, НЕ указывайте первичный ключ с db.add() или db.merge().

Вот примеры, которые я использовал для выяснения того, что подразумевала червя.

# Suppose the next value of rows_id_seq will be 33.
# You run the following code.
db.add(Row(id=35))
# Since you specified a primary key, SQLAlchemy will NOT increment rows_id_seq,
# so the next value of rows_id_seq will still be 33.
db.add(Row())
# The next value of rows_id_seq will be 34
db.add(Row())
# The next value of rows_id_seq will be 35
db.add(Row())
db.query(Row.id).all() # Uh-oh
# (IntegrityError) duplicate key value violates unique constraint "rows_pkey"
# Key (id)=(35) already exists.

Вот пример использования db.merge().

# Suppose the next value of rows_id_seq will be 1.
# You run the following code.
db.merge(Row(id=1))
db.merge(Row(id=2))
db.merge(Row(id=3))
# Since you specified a primary key, SQLAlchemy will NOT increment rows_id_seq,
# so the next value of rows_id_seq will still be 1.
db.merge(Row())
db.query(Row.id).all() # Uh-oh
# (IntegrityError) duplicate key value violates unique constraint "rows_pkey"
# Key (id)=(1) already exists.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню