2011-08-12 12 views
1

前回の質問では、IDを持つインスタンスをデータベースに初めてマージするとき(フィクスチャデータを注入する)、なぜSAからインテグリティエラーが発生したのか不思議でした。しかし、これは私が苦労してる何である、根本的な問題を解決していないインスタンスをマージするときにPostgreSQLがid_sequenceのlast_valueを増やさないのはなぜですか?

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

を:

はしかし、私は私が注入てる最高のインデックスで呼び出すことにより、問題を説明するために学びました今。なぜ新しい行を挿入するときにシーケンスの呼び出しnextval()をマージしないのですか?

答えて

3

オブジェクトにすでにPK属性が設定されている場合、暗黙のうちにデータベースが実行される理由がないため、IDシーケンスは使用されず、したがってインクリメントされません。insert into mytable (id, ...) values ((select nextval from mytable_id_seq), ...)

あなたのsessionaddの代わりにmergeを実行する必要がありますか?あなたが本当に挿入しているのであれば、それはaddの操作以上のものだと思います。まだメモリに残っているオブジェクトを再利用するだけで、以前にデータベースに追加した可能性がある場合は、mergeが適切です。

+0

wberryが正しいです。マージを使用すると、切断されたオブジェクトまたはオブジェクトが別のセッションから取り込まれます。これらが 'new'オブジェクトであれば、' add'を使う必要があります。 'setval'を使うと、あなたのテーブルにすでに存在しているidとは無関係にシーケンスの現在の値が強制的に更新されます。新しいオブジェクトを追加する前にテーブルデータをクリアしていなければ、 –

0

私はこの記事が見つかるまで、PostgreSQLのIntegrityErrorsと同じ問題で苦労しました。私は次の規則に従うことにしました:オブジェクトがデータベースに存在しない場合は、db.add()またはdb.merge()で主キーを指定しないでください。

ここに私がwberryの意味を理解するために使用した例があります。

# 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. 
関連する問題