我必须对恰好在同一个MySQL实例中的两个不同模式中传播的表进行一些查询。使用SQL,这很简单,只需在表名前加上模式名称(假设a和be是模式名称):
SELECT upeople.id AS upeople_id
FROM a.upeople JOIN b.changes ON upeople.id = changes.changed_by
在SQLAlchemy中,似乎可以使用两个引擎来使用它。在阅读文档后,在我看来,下面的代码应该可以工作(使用两个不同的模式名称的棘手部分):
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.query import Query
Base = declarative_base(cls=DeferredReflection)
BaseId = declarative_base(cls=DeferredReflection)
class Changes(Base):
__tablename__ = 'changes'
class UPeople(BaseId):
__tablename__ = 'upeople'
database='mysql://jgb:XXX@localhost/a'
id_database='mysql://jgb:XXX@localhost/b'
engine = create_engine(database)
id_engine = create_engine(id_database)
Base.prepare(engine)
BaseId.prepare(id_engine)
bindings = {Changes: engine,
UPeople: id_engine}
Session = sessionmaker(binds=bindings)
session = Session()
q = session.query(UPeople.id).join(Changes,
UPeople.id == Changes.changed_by)
print q
但事实并非如此。当我执行q(例如q.all())时,它失败了。 “print q”显示没有模式名称的查询:
SELECT upeople.id AS upeople_id
FROM upeople JOIN changes ON upeople.id = changes.changed_by
而不是我的预期:
SELECT upeople.id AS upeople_id
FROM a.upeople JOIN b.changes ON upeople.id = changes.changed_by
我在这里缺少什么?
BTW,我发现通过添加 table_args ,例如:
class Changes(Base):
__tablename__ = 'changes'
__table_args__ = {'schema': 'a'}
(对于两个表),它的工作原理。但是想知道为什么其他代码没有...另外,我在声明表的类时没有模式名称,意味着我无法使用 table_args 技巧...
所以,总结一下:如何使用来自两个模式的表来查询“好方法”,并且如果可能的话,我在声明Table类时不需要包含名称,但稍后,当引擎和会话时定义了吗?
答案 0 :(得分:1)
我没有找到为什么代码不起作用,我倾向于认为它是SQLAlchemy中的一个错误。但是,我找到了一种使类似代码工作的方法。它最终依赖于使用__table_args__
来定义模式。但由于我在运行时之前没有模式的名称,因此我使用以下函数动态定义表的类:
def table_factory (name, tablename, schemaname):
table_class = type(
name,
(Base,),
dict (
__tablename__ = tablename,
__table_args__ = {'schema': schemaname}
)
)
return table_class
这为名为“tablename”的表创建了一个类(名称为“name”),但是如果指定了包含模式名称。
使用此解决方案的代码与问题中的代码非常类似,如下所示:
Base = declarative_base()
database='mysql://jgb:XXX@localhost/'
Changes = table_factory (name = "Changes",
tablename = "changes",
schemaname = 'a')
UPeople = table_factory (name = "UPeople",
tablename = "upeople",
schemaname = 'b')
engine = create_engine(database)
Base.prepare(engine)
Session = sessionmaker(bind=engine)
session = Session()
q = session.query(UPeople.id).join(Changes,
UPeople.id == Changes.changed_by)
print q
现在,它打印出来:
SELECT b.upeople.id AS b_upeople_id
FROM b.upeople JOIN a.changes ON b.upeople.id = a.changes.changed_by
其中包括模式名称。