массовое обновление sqlalchemy завершается неудачно - PullRequest
0 голосов
/ 27 марта 2020

У меня есть таблица = foo (минимальный пример ниже):

house       processed
----------  ----------
95.0
10.0
63.0
6.0
55.0
1.0
19.0
1.0
30.0
21.0
sprite

Я хочу изменить десятичные значения на целые и выяснить, когда в этом столбце есть нечисловое значение c. Я пробовал с конструкцией query.filter().update(), и хотя это дает мне то, что я хочу, для 100k строк это занимает вечность. Я понял, bulk_update может мне помочь. Но я могу сделать что-то не так. Мой код:

class foo(Base):
    __tablename__ = "foo"
    rowid = Column(Integer, primary_key=True)
    house = Column(Float)
    processed = Column(String(255))

mappings = []
for idx, s in enumerate(session.query(foo), start=1):    
    if type(s.house) in (int, float):
        replace = int(s.house)            
        info = {'processed':replace}
    else:
        info = {'processed':'not number'}        
    mappings.append(info)  
session.bulk_update_mappings(foo, mappings)
session.commit()

отображения [{'обработано': 95}, {'обработано': 10}, {'обработано': 63}, {'обработано': 6}, {'обработано': 55}, {'обработано': 1}, {'обработано': 19}, {'обработано': 1}, {'обработано': 30}, {'обработано': 21}, {' обработано ':' not number '}]

Это дает мне ошибку:

Оператор UPDATE для таблицы' foo ', как ожидается, обновит 11 строк; 0 совпадений

Полная ошибка:

session.bulk_update_mappings(foo, mappings)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\M64H098\repo\Enrichments-bag\lib\site-packages\sqlalchemy\orm\session.py", line 2868, in bulk_update_mappings
    self._bulk_save_mappings(
  File "C:\Users\M64H098\repo\Enrichments-bag\lib\site-packages\sqlalchemy\orm\session.py", line 2885, in _bulk_save_mappings
    transaction = self.begin(subtransactions=True)
  File "C:\Users\M64H098\repo\Enrichments-bag\lib\site-packages\sqlalchemy\orm\session.py", line 947, in begin
    self.transaction = self.transaction._begin(nested=nested)
  File "C:\Users\M64H098\repo\Enrichments-bag\lib\site-packages\sqlalchemy\orm\session.py", line 316, in _begin
    self._assert_active()
  File "C:\Users\M64H098\repo\Enrichments-bag\lib\site-packages\sqlalchemy\orm\session.py", line 288, in _assert_active
    raise sa_exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: UPDATE statement on table 'foo' expected to update 11 row(s); 0 were matched. (Background on this error at: http://sqlalche.me/e/7s2a)

Что можно сделать, чтобы массово обновить столбец processed с помощью словаря mapping?

1 Ответ

1 голос
/ 30 марта 2020

bulk_update_mappings требует, чтобы первичные ключи для обновляемых строк были включены в словари обновлений. Это имеет смысл, когда вы думаете об этом - должен быть способ для базы данных идентифицировать строки, которые должны быть обновлены. В этом случае первичными ключами будут rowid s Foo модели.

info = {'rowid': s.rowid, 'processed':replace}

Из документов (выделено мной):

последовательность словари, ... Все те ключи, которые присутствуют и не являются частью первичного ключа, применяются к предложению SET инструкции UPDATE; значения первичного ключа, которые требуются , применяются к предложению WHERE.

...