3

我有一张Track桌子和一张Artist桌子。该Artist表有一个idTrack表有一个外键,artist_id。我想删除所有没有关联曲目的艺术家。

在 SQL 中:

delete from artists 
 where id in (select artists.id
                from artists left outer join tracks 
                  on tracks.artist_id = artists.id
               where tracks.id is null);

效果很好。但是当我尝试在 SQLAlchemy 中复制它时:

artists = session.query(Artist.id).outerjoin((Track, Artist.id == Track.artist_id)).filter(Track.id == None)
print('deleting %d unused artists' % artists.count())
session.query(Artist).filter(Artist.id.in_(artists.all())).delete()

工作print()正常(并显示正确的行数)但删除给出了错误:

...
sqlalchemy.orm.evaluator.UnevaluatableError: Cannot evaluate clauselist with operator <function comma_op at 0x2d3e0d8>
During handling of the above exception, another exception occurred:
...
"Could not evaluate current criteria in Python. "
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter.

那么我如何在 SQLAlchemy 中做到这一点?我不介意方法是否不同,只要我可以删除所有不属于任何轨道的艺术家。

PS我也尝试过artists.delete()(在选择Artist实例时,而不是上面的ID),这也给出了一个错误——在这种情况下,外连接“丢失”并且SQL不一致。

更新

万一这对任何人都有用,如果您artists的模型中有一个反向引用(,下面),则有一种比外连接更简单的方法:

session.query(Artist).filter(Artist.tracks == None).delete(synchronize_session=False)
4

1 回答 1

4

例外是确切地告诉您如何解决问题,您需要将 a 指定synchronize_session"fetch"or之一False。Sqlalchemy 试图避免做一些额外的工作,通过session将删除直接应用于 python 对象来更新附加到的对象的状态以反映数据库中的更改。

不幸的是,它不能为这个查询做到这一点,所以你需要告诉它要么“获取”活动Artist的 s 以查看它们是否被删除,或者只是忽略它,并使会话处于无效状态。

您还会在in_(query.all())制作过程中遇到麻烦;因为 sqlalchemy 不知道如何绑定元组列表,并且也是原始查询的不完美再现。就够in_(query)了。

于 2013-02-18T05:40:37.777 回答