2015-10-29 60 views
1

我正在使用Session.bulk_insert_mappings()插入一些實體,但當實體具有None值時,我遇到問題。SQLAlchemy批量插入空柱子

以下批量插入正常工作,單個插入語句來插入所有實體:

session.bulk_insert_mappings(Document, [ 
    dict(document_id=1, version=1, colA=True, colB='a'), 
    dict(document_id=2, version=1, colA=True, colB='b'), 
    dict(document_id=3, version=1, colA=True, colB='c') 
]) 

但是當字段爲None,SQLAlchemy的將分裂插入多個語句:

session.bulk_insert_mappings(Document, [ 
    dict(document_id=1, version=1, colA=True, colB='a'), 
    dict(document_id=2, version=1, colA=True, colB=None), 
    dict(document_id=3, version=1, colA=True, colB='c') 
]) 

登錄:

INFO [...] INSERT INTO api.documents (...) VALUES (...) 
INFO [...] {'colA': True, 'colB': 'a', 'version': 1, 'document_id': 1} 
INFO [...] INSERT INTO api.documents (...) VALUES (...) 
INFO [...] {'colA': True, 'version': 1, 'document_id': 2} 
INFO [...] INSERT INTO api.documents (...) VALUES (...) 
INFO [...] {'colA': True, 'colB': 'c', 'version': 1, 'document_id': 3} 

我試着與null()取代None,但後來我收到以下錯誤「無法適應型‘空’」:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Null' [SQL: 'INSERT INTO api.documents (...) VALUES (...)'] [parameters: ({'colB': 'a', 'colA': True, 'version': 1, 'document_id': 1}, {'colB': <sqlalchemy.sql.elements.Null object at 0x7f74679c0190>, 'colA': True, 'version': 1, 'document_id': 2}, {'colB': 'c', 'colA': True, 'version': 1, 'document_id': 3})] 

我怎樣才能確保單個插入語句甚至被用來當一些實體None值?

編輯:映射是這樣的:

class Document(Base): 
    __tablename__ = 'documents' 

    document_id = Column(Integer, primary_key=True) 
    version = Column(Integer, nullable=False, server_default='1') 
    colA = Column(Boolean) 
    colB = Column(Integer) 
+0

你有沒有試圖省略'colB'? –

+0

@TomaszJakubRup我剛剛嘗試過,但結果相同(3個插入語句被創建)。 – tsauerwein

+0

請顯示一個'mapper'類('Document') –

回答

2

繼SQLAlchemy的文檔http://docs.sqlalchemy.org/en/latest/orm/persistence_techniques.html

如果我們希望能夠使用Python值無和有這個 也會被保留爲NULL,儘管存在列默認值,我們 可以使用核心級別修改器爲ORM配置此類型TypeEng ine.evaluates_none(),它表示類型,其中ORM 應該把值沒有相同的任何其他值,並將它傳遞 通過,而不是忽略它作爲「丟失」的值:

class MyObject(Base): 
    __tablename__ = 'my_table' 
    id = Column(Integer, primary_key=True) 
    data = Column(
     String(50).evaluates_none(), # indicate that None should always be passed 
     nullable=True, server_default="default") 

obj = MyObject(id=1, data=None) 
session.add(obj) 
session.commit() # INSERT with the 'data' column explicitly set to None; 
        # the ORM uses this directly, bypassing all client- 
        # and server-side defaults, and the database will 
        # persist this as the NULL value 

這可能解決您的問題。

+0

對不起,回覆遲了,謝謝你的回答。您的解決方案有效,但我想避免更改模型,因爲它僅適用於遷移腳本,我不希望普通應用程序受到影響。你也可以用'TypeEngine.should_evaluate_none = True'來全局設置它,我將不得不測試它是否適用於我的情況。 – tsauerwein