2016-04-03 31 views
1

我有以下的模型,其中表A和表B有1對1的關係:SQLAlchemy的批量插入有一對一的關係

class TableA(db.Model): 
    id = Column(db.BigInteger, primary_key=True) 
    title = Column(String(1024)) 
    table_b = relationship('TableB', uselist=False, back_populates="table_a") 


class TableB(db.Model): 
    id = Column(BigInteger, ForeignKey(TableA.id), primary_key=True) 
    a = relationship('TableA', back_populates='table_b') 
    name = Column(String(1024)) 

當我插入1記錄一切順利:

rec_a = TableA(title='hello') 
rec_b = TableB(a=rec_a, name='world') 
db.session.add(rec_b) 
db.session.commit() 

但當我嘗試做大量的記錄:

bulk_ = [] 

for title, name in zip(titles, names): 
    rec_a = TableA(title=title) 
    bulk_.append(TableB(a=rec_a, name=name)) 

db.session.bulk_save_objects(bulk_) 
db.session.commit() 

我收到以下例外:

sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1364, "Field 'id' doesn't have a default value") 

我做錯了什麼?我配置模型錯了嗎? 有沒有辦法批量提交這種類型的數據?

回答

3

您看到的錯誤是由Mysql拋出的。它抱怨試圖將記錄插入table_b違反了外鍵約束。

一種技術可能是將所有標題寫入一個批量語句中,然後將所有名稱寫入第二個批量語句中。另外,我從未將關係成功地傳遞給批量操作,因爲此方法依賴於插入簡單的值。

bulk_titles = [TableA(title=title) for title in titles] 
session.bulk_save_objects(bulk_titles, return_defauls=True) 
bulk_names = [TableB(id=title.id, name=name) for title, name in zip(bulk_titles, names)] 
session.bulk_save_objects(bulk_names) 

return_defaults=True需要上面,因爲我們在第二個批量操作需要title.id。但是,這可以避免由於return_defauts=True而造成的性能下降,您可以從應用程序生成主鍵,而不是數據庫。使用uuids,或獲取每個表中的最大id並從該起始值生成一個範圍。

另一種技術可能是使用sqlalchemy核心或純文本編寫批量插入語句。