Database SQLAlchemy声明+跨多个不同数据库的关系

Database SQLAlchemy声明+跨多个不同数据库的关系,database,sqlalchemy,relationship,declarative,Database,Sqlalchemy,Relationship,Declarative,这花了我一段时间,但我发现了如何使用SQLAlchemy跨两种不同类型的数据库建模关系: 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) # B

这花了我一段时间,但我发现了如何使用SQLAlchemy跨两种不同类型的数据库建模关系:

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
我必须这样做,因为术语表在Oracle数据库中,我只有读取权限,我正在编写一个应用程序,记录学生对该术语的调查

上面的方法是有效的,但是当表的数量增加时,它是非常脆弱的,因为会话需要精确地指定哪些映射类对应于哪个引擎。我真的希望能够使用不同的基来定义哪些表属于哪个引擎,而不是单独绑定每个表。像这样:

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:初始化mapper mapper | Survey | Survey时,表达式“Term.Term_id==Survey.Term_id”未能找到名称,未定义名称“Term”。如果这是类名,请考虑在定义了两个依赖类之后将该关系添加到类。p> 即使我在定义了这个术语之后,将这个关系添加到了调查中


有人有什么建议吗?

你没有。抱歉,没有针对两个不同数据库的单一查询。此外,您的模型必须共享要在同一查询中使用的相同元数据实例

也许您可以通过ODBC将Oracle数据库链接到数据库层上的MySQL数据库,然后只与MySQL对话。我从来没有这样做过,我不知道它是如何工作的


您还可以独立地查询两个数据库,并在应用程序层上筛选和选择数据,以工作量较小的为准。

此回复可能很晚,但您可以将元数据与声明性基础分开定义,然后将其传递给这两个数据库。即:

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

MySQLBase = declarative_base(bind=mysql_engine, metadata=meta)
OracleBase = declarative_base(bind=oracle_engine, metadata=meta)

我想可能是这样的。不过,我不知道您的模型需要共享元数据才能在同一个查询中。很高兴知道。嗯,4年前我问这个问题时,我不确定这是否可行。不过,这对未来的谷歌用户来说非常有用!未来的谷歌:有没有一种方法可以用来替代第三方模块中类的基继承?我正在尝试编写一些代码,这些代码将从与另一个DB对象的关系中获益,但目前我认为最好的方法是复制该代码的模型类,唯一的更改是从不同的基继承。@mpouncet我认为您所要求的不仅是可能的,而且也是我使用它的目的。自从我参与这个项目已经有几年了,所以我不能说这项技术是否仍然有效。理论上,你可以使用一个动态填充一个dict,其中的类映射到哪个引擎。或者在通过MySQLBase绑定会话时动态检查MySQLBase/OracleBase的所有子类。我还没有测试过