2011-08-12 20 views
1

在上一個問題中,我想知道爲什麼當第一次將帶有ID的實例合併到數據庫(注入fixture數據)時,我從SA中獲得完整性錯誤。爲什麼PostgreSQL在合併實例時不會增加id_sequence的last_value?

不過,我學會了考慮這個問題與我注射指數最高美其名曰:

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

然而,這並沒有解決根本問題,這是我與掙扎現在。爲什麼在插入新行時不在序列上合併call nextval()?

回答

3

如果您的對象已經設置了PK屬性,那麼ID序列將不會被使用,因此不會增加,因爲數據庫沒有理由執行隱式insert into mytable (id, ...) values ((select nextval from mytable_id_seq), ...)

您確定您需要爲您的session做一個merge而不是add嗎?如果你真的插入,我會認爲這是更多的add操作。如果您只是重複使用仍在內存中的對象,但之前已添加並可能已在數據庫中進行更改,則merge是合適的。

+0

wberry是正確的。您只能使用合併從另一個會話中引入斷開連接的對象或對象。如果這些是你創建的'new'對象,那麼你需要使用'add'。請記住,使用'setval'會強制序列的當前值,而不管表中的id可能已經存在 - 如果在添加新對象之前尚未清除表數據,則可能會出現密鑰重疊和完整性錯誤。 –

0

我在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. 
相關問題