私はTrack
テーブルとテーブルを持っていArtist
ます。Artist
テーブルには がid
あり、テーブルTrack
には外部キー があり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()
(上記のIDの代わりにArtistインスタンスを選択しながら)試してみましたが、これもエラーが発生しました-その場合、外部結合が「失われ」、SQLに一貫性がありません。
アップデート
artists
これが誰にとっても役立つ場合、モデルに backref (下の )がある場合は、外部結合よりもはるかに簡単なアプローチがあります。
session.query(Artist).filter(Artist.tracks == None).delete(synchronize_session=False)