2014-09-21 122 views
20

我想在使用SQLAlchemy模塊(不是SQL!)的python中編寫批量upsert。SQLAlchemy - 在postgresql中執行批量upsert(如果存在,更新,否則插入)

我得到一個SQLAlchemy的下面的錯誤添加:

sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "posts_pkey" 
DETAIL: Key (id)=(TEST1234) already exists. 

我有一個表叫posts與上id列主鍵。

在這個例子中,我已經在db中有一行id=TEST1234。當我試圖db.session.add()一個新的帖子對象與id設置爲TEST1234,我得到上述錯誤。我的印象是,如果主鍵已經存在,記錄會被更新。

如何根據主鍵單獨添加Flask-SQLAlchemy?有一個簡單的解決方案嗎?

如果沒有,我總是可以檢查並刪除任何帶有匹配ID的記錄,然後插入新記錄,但這對我的情況來說似乎很昂貴,我不希望有很多更新。

+0

有一個在SQLAlchemy中沒有更新插入操作,這是一般人很難即使在SQLAlchemy之外也能正確執行。顯示你正在做什麼來得到這個錯誤。 – davidism 2014-09-22 01:01:02

+1

@davidism合併操作就像一個upsert – mgoldwasser 2014-09-24 14:04:46

+1

* SQLAlchemy的'merge'不是upsert *,[upserts很難](http://lucumr.pocoo.org/2014/2/16/a-case-for -upserts /)。 merge並不是線程安全的,全部都是用Python完成的,而不是數據庫。 – davidism 2014-09-24 14:45:34

回答

16

有一個在SQLAlchemy的一個更新插入式的操作:

db.session.merge()

我發現這個命令後,我能夠執行upserts,但值得一提的是,該操作是批量慢「更新插入」。

另一種方法是讓你想UPSERT主鍵的列表,並查詢任何匹配的IDS數據庫:

# Imagine that post1, post5, and post1000 are posts objects with ids 1, 5 and 1000 respectively 
# The goal is to "upsert" these posts. 
# we initialize a dict which maps id to the post object 

my_new_posts = {1: post1, 5: post5, 1000: post1000} 

for each in posts.query.filter(posts.id.in_(my_new_posts.keys())).all(): 
    # Only merge those posts which already exist in the database 
    db.session.merge(my_new_posts.pop(each.id)) 

# Only add those posts which did not exist in the database 
db.session.add_all(my_new_posts.values()) 

# Now we commit our modifications (merges) and inserts (adds) to the database! 
db.session.commit() 
+3

合併不處理intigirtyError – 2016-02-04 12:02:02

+1

上面的過程很慢,無法使用 – 2016-02-04 12:03:21

+1

替代方案是SQLAlchemy中upsert的一個很好的解決方案 – 2016-08-19 16:07:33

相關問題