2015-10-29 2 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') 
]) 

Log:

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 значения?

Edit: отображение выглядит следующим образом:

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 None и есть этот также сохраняется как NULL, несмотря на наличие значений по умолчанию для столбцов, мы можем настроить это для ORM с использованием модификатора основного уровня TypeEng ine.evaluates_none(), который указывает тип, где ОРМ должны относиться к значение Нет такой же, как любое другое значение и передать его через , а не пропуская его как «отсутствует» значение:

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

Смежные вопросы