2017-11-10 6 views
4

を接合継承を使用して、次のSQLAlchemyのマッピングを考える:SQLAlchemyのメンバー継承速いバルク削除オブジェクト

from sqlalchemy import sa 

class Location(Base): 
    id = Column(Integer, primary_key=True) 
    name = sa.Column(sa.String) 
    type_ = sa.column(sa.String) 

    __tablename__ = 'location' 
    __mapper_args__ = { 
     'polymorphic_identity': 'location', 
     'polymorphic_on': type_, 
    } 

class Field(Location): 
    id = Column(Integer, primary_key=True) 
    size = sa.Column(sa.Float) 

    __tablename__ = 'field' 
    __mapper_args__ = { 
     'polymorphic_identity': 'field', 
    } 
    __table_args__ = (
     sa.ForeignKeyConstraint(['id'], ['location.id']), 
    ) 


session.query(Field).filter(Field.size < 5).delete() 

どこ塩基は、適切な宣言型ベースであり、セッションが適切なセッション・オブジェクトです。上記の実装により、親Locationオブジェクトが削除されずにフィールドオブジェクトが削除されます(ドキュメントが明確に説明しているので、query.delete()は継承をサポートしていません)。私はsession.delete(obj)をORMを使ってチェインの上にあるオブジェクトを削除することで回避することができます。ただし、nデータベースでSQL削除ステートメントが実行されます(nは削除するオブジェクトの数です)。私は一度に10万の子オブジェクトのオーダーで削除するかもしれないケースがあるので、この操作は恐ろしく遅いです(私がではなく、を継承継承で使用することは不可能です。これを変更するには深く)。

SQLAlchemyの内のいずれかの構築物または私はタイプFieldのオブジェクトを照会し、適切N SQLの文を削除せずに、同様Locationテーブル内の項目を削除し、クエリオブジェクトを渡すことができるようになる合理的な代替手段はありますか?

私は現在PostgreSQLを使用していますが、解決策をdb-agnosticにしたいと考えています。

編集:リクエストごとに環境に関するテーブルのメタデータと詳細情報が追加されました。

+0

であるあなたが使用して、プライマリキーと外部キー定義されているものをDB記載してください。あなたはおそらくこれのためにCoreを使うことができます。 –

答えて

0

1〜2時間試してみると、あまりコードがない解決策が見つかりました。それから私はそれを再現します。

私はdelete()の文書をチェックします。 2つの文があります。

このメソッドは継承マッパーの参加条件は、自動的に

レンダリングされていないことを、複数のテーブルの削除がSQLでサポートされていないことから、参加継承マッピングのために働くだけでなく、しません。 CASCADEルールを削除しない限り、ON

上記のSQLは、エンジニアテーブルから削除されませんしかし

は、それを処理するためにデータベースに確立されています。

短編小説では、これを実行可能にするために追加の手順を踏んでいない限り、結合された継承マッピングにこのメソッドを使用しないでください。

したがって、外部キー制約を定義する必要があります。このように:私たちは削除場合は今

class Location(Base): 
    __tablename__ = 'location' 
    id = Column(INTEGER, primary_key=True) 
    name = Column(VARCHAR(30)) 
    type = Column(VARCHAR(30)) 

    __mapper_args__ = { 
     'polymorphic_identity': 'location', 
     'polymorphic_on'  : type, 
    } 

class Field(Location): 
    __tablename__ = 'field' 
    id = Column(INTEGER, ForeignKey('location.id', ondelete='cascade'), primary_key=True) 
    size = Column(DECIMAL(20, 2)) 

    __mapper_args__ = { 
     'polymorphic_identity': 'field', 
    } 

2.Locationは、Fieldの行も削除されています。

session.query(Location).filter(Location.id == 1).delete() 

3。しかし、ポスターはないLocationFieldを削除したいです。

session.query(Field).filter(Field.size < 5).delete() 

これはLocationの行せずFieldで行を削除します。 Fieldは外部表であるため、メイン表をカスケードできません。

ここで、LocationからField.size < 5に従って削除する必要があります。

私はこれらの両方の例外をスロー

session.query(Location).filter(Field.size < 5).delete() 

session.query(Location).outerjoin(Field, Location.id == Field.id).filter(Field.size < 5).delete() 

を試してみました。

多くがしようとした後、溶液は私FOUNDはこれです:

statment = delete(Field, prefixes=[Location.__tablename__]).where(Field.size == 1) 
session.execute(statment) 

生成されたSQLがDELETE location FROM location JOIN field ON location.id = field.id WHERE field.size < 5

関連する問題