13

少し時間がかかりましたが、SQLAlchemy を使用して 2 つの異なる種類のデータベース間の関係をモデル化する方法を見つけました。

Base = declarative_base()

class Survey(Base):
    __tablename__ = 'SURVEY'

    survey_id = Column("SURVEY_ID", Integer, primary_key=True)
    term_id = Column("TERM_ID", Integer, nullable=False)

    # Because the TERM table is in Oracle, but the SURVEY table is in
    # MySQL, I can't rely on SQLAlchemy's ForeignKey.  Thus,
    # I need to specify the relationship entirely by hand, like so:
    term = relationship("Term",
        primaryjoin="Term.term_id==Survey.term_id",
        foreign_keys=[term_id],
        backref="surveys"
    )

class Term(Base):
    __tablename__ = 'TERM'

    term_id   = Column(Integer, primary_key=True)
    term_name = Column(String(30))
    start_date = Column(Date)
    end_date = Column(Date)

mysql_engine = create_engine(MYSQL)
oracle_engine = create_engine(ORACLE)

Session = scoped_session(sessionmaker(
    binds={
        Term: oracle_engine,
        Survey: mysql_engine
    }
))

if __name__ == "__main__":
    survey = Session.query(Survey).filter_by(survey_id=8).one()
    print survey.term
    print survey.term.surveys

これを行う必要があるのは、TERM テーブルが読み取りアクセス権しかない Oracle データベースにあり、学生がその学期について行った調査を記録するアプリを作成しているためです。

上記は機能しますが、テーブルの数が増えると非常に壊れやすくなります。これは、Session が、どのマップされたクラスがどのエンジンに対応するかを正確に指定する必要があるためです。Base各テーブルを個別にバインドするのではなく、別の を使用して、どのテーブルがどのエンジンに属しているかを定義できるようにしたいと考えています。このような:

mysql_engine = create_engine(MYSQL)
oracle_engine = create_engine(ORACLE)

MySQLBase = declarative_base(bind=mysql_engine)
OracleBase = declarative_base(bind=oracle_engine)

class Survey(MySQLBase):
    __tablename__ = 'SURVEY'

    survey_id = Column("SURVEY_ID", Integer, primary_key=True)
    term_id = Column("TERM_ID", Integer, nullable=False)


class Term(OracleBase):
    __tablename__ = 'ads_term_v'

    term_id   = Column(Integer, primary_key=True)
    term_name = Column(String(30))
    start_date = Column(Date)
    end_date = Column(Date)

Survey.term = relationship("Term",
    primaryjoin="Term.term_id==Survey.term_id",
    foreign_keys=[Survey.term_id],
    backref="surveys"
)

Session = scoped_session(sessionmaker())

if __name__ == "__main__":
    survey = Session.query(Survey).filter_by(survey_id=8).one()
    print survey.term
    print survey.term.surveys

残念ながら、これにより、クエリの実行時に次のエラーが発生します。

sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|Survey|SURVEY, expression 'Term.term_id==Survey.term_id' failed to locate a name ("name 'Term' is not defined"). If this is a class name, consider adding this relationship() to the <class '__main__.Survey'> class after both dependent classes have been defined.

Term が定義された後に Relationship() を Survey に追加しましたが

誰か提案はありますか?

4

2 に答える 2

3

できません。私の知る限り、2 つの異なるデータベースに対する単一のクエリはありません。また、モデルは、同じクエリで使用される同じ Metadata インスタンスを共有する必要があります。

おそらく、ODBC 経由で Oracle db を DB 層の MySQL db にリンクすることができます。そうすれば、MySQL とのみ対話できます。私はこれをやったことがなく、どのように機能するのかわかりません。

また、両方のデータベースに個別にクエリを実行し、アプリケーション レイヤーでデータをフィルター処理して選択することもできます。

于 2011-09-15T20:37:12.477 に答える