我使用Session.bulk_insert_mappings()来插入多个实体,但是当实体有None
个值时,我遇到了问题。
以下批量插入工作正常,单个插入语句用于插入所有实体:
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}
我尝试将None
替换为null(),但后来我收到以下错误"无法调整类型' Null'" :
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 :(得分:2)
遵循SQLAlchemy文档http://docs.sqlalchemy.org/en/latest/orm/persistence_techniques.html:
如果我们希望能够使用Python值而无法使用它 尽管存在列默认值,我们也可以保持为NULL 可以使用Core级修饰符为ORM配置此项 TypeEngine.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
这可能解决了你的问题。