Как удалить строки из таблицы с помощью запроса SQLAlchemy без ORM?
Я пишу быстрый и грязный mainteace script для удаления некоторых строк и хотел бы избежать необходимости переносить классы/сопоставления ORM из основного проекта. У меня есть запрос, похожий на:
address_table = Table('address',metadata,autoload=True)
addresses = session.query(addresses_table).filter(addresses_table.c.retired == 1)
В соответствии со всем, что я прочитал, если я использовал ORM (не "только" таблицы) и передал что-то вроде:
addresses = session.query(Addresses).filter(addresses_table.c.retired == 1)
Я мог бы добавить .delete()
к запросу, но когда я попытаюсь сделать это, используя только таблицы, я получаю жалобу:
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 2146, in delete
target_cls = self._mapper_zero().class_
AttributeError: 'NoneType' object has no attribute 'class_'
Это имеет смысл как его таблица, а не класс. Я очень зелёный, когда дело доходит до SQLAlchemy, как я должен это делать?
Ответы
Ответ 1
Просмотрев какой-то код, где я сделал что-то подобное, я считаю, что это сделает то, что вы хотите.
d = addresses_table.delete(addresses_table.c.retired == 1)
d.execute()
Вызов sql.expression
delete()
для объекта таблицы дает вам sql.expression
(если используется память), которое вы затем выполняете. Я предположил, что таблица привязана к соединению, что означает, что вы можете просто вызвать execute()
на нем. Если нет, вы можете передать d
для execute(d)
в соединении.
См. Документы здесь.
Ответ 2
Когда вы вызываете delete()
из объекта запроса, SQLAlchemy выполняет массовое удаление. И вам нужно выбрать стратегию для удаления согласованных объектов из сеанса. См. Документацию здесь.
Если вы не выбрали стратегию удаления согласованных объектов из сеанса, то SQLAlchemy попытается оценить критерии запросов в Python прямо на объектах в сеансе. Если оценка критериев не реализована, возникает ошибка.
Это то, что происходит с вашим удалением.
Если вы хотите удалить записи и не заботиться о записях в сеансе после удаления, вы можете выбрать стратегию, которая игнорирует синхронизацию сеанса:
address_table = Table('address', metadata, autoload=True)
addresses = session.query(address_table).filter(address_table.c.retired == 1)
addresses.delete(synchronize_session=False)