在上一個問題中,我想知道爲什麼當第一次將帶有ID的實例合併到數據庫(注入fixture數據)時,我從SA中獲得完整性錯誤。爲什麼PostgreSQL在合併實例時不會增加id_sequence的last_value?
不過,我學會了考慮這個問題與我注射指數最高美其名曰:
select setval('my_items_id_seq', {id});
然而,這並沒有解決根本問題,這是我與掙扎現在。爲什麼在插入新行時不在序列上合併call nextval()?
在上一個問題中,我想知道爲什麼當第一次將帶有ID的實例合併到數據庫(注入fixture數據)時,我從SA中獲得完整性錯誤。爲什麼PostgreSQL在合併實例時不會增加id_sequence的last_value?
不過,我學會了考慮這個問題與我注射指數最高美其名曰:
select setval('my_items_id_seq', {id});
然而,這並沒有解決根本問題,這是我與掙扎現在。爲什麼在插入新行時不在序列上合併call nextval()?
如果您的對象已經設置了PK屬性,那麼ID序列將不會被使用,因此不會增加,因爲數據庫沒有理由執行隱式insert into mytable (id, ...) values ((select nextval from mytable_id_seq), ...)
。
您確定您需要爲您的session
做一個merge
而不是add
嗎?如果你真的插入,我會認爲這是更多的add
操作。如果您只是重複使用仍在內存中的對象,但之前已添加並可能已在數據庫中進行更改,則merge
是合適的。
我在PostgreSQL中一直困擾着IntegrityErrors,直到找到這篇文章。我決定堅持以下規則:如果對象不存在於數據庫中,請不要使用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.
wberry是正確的。您只能使用合併從另一個會話中引入斷開連接的對象或對象。如果這些是你創建的'new'對象,那麼你需要使用'add'。請記住,使用'setval'會強制序列的當前值,而不管表中的id可能已經存在 - 如果在添加新對象之前尚未清除表數據,則可能會出現密鑰重疊和完整性錯誤。 –