我正在使用declarative_base()并尝试弄清楚在使用多对多关系时如何强制执行延迟内连接。
我在MySQL和InnoDB中有表定义了外键约束。
users: userid, name
permissions: permissionid, name
users_permissions: userid, permissionid
我正在使用metadata.reflect()
来加载我的数据库。
class User_Perm(Base):
__table__ = Base.metadata.tables['users_permissions']
class User(Base):
__table__ = Base.metadata.tables['users']
permissions = orm.relationship('Permission',
secondary=User_Perm.__table__,
order_by='Perm.name',
innerjoin=True,
lazy=True,
)
class Permission(Base):
__table__ = Base.metadata.tables['permissions']
每当我选择
u = Session().query(User).filter(User.name == 'myuser').first()
u.permissions
MySQL服务器收到的查询是:
SELECT permissions.permissionid AS permissions_permissionid,
permissions.name AS permissions_name
FROM permissions, users_permissions
WHERE ? = users_permissions.userid
AND permissions.permissionid = users_permissions.permissionid
ORDER BY permissions.name
正如我们所看到的,FROM permissions, users_permissions
不是内连接。我是否可以在不需要使用lazy=False
的情况下强制执行此操作,因为如果我这样做,则级联效果将加载太多信息,因为permissions
也与另一个表(示例中未提及)和users
也与其他表相关(同样,在示例中未提及)。我想为我所有的课程使用相同的模板来建立关系。
编辑:上下文我正在尝试复制所有SQL查询以匹配当前系统中的查询。我正在尝试从oursql
迁移到sqlalchemy orm
。
答案 0 :(得分:3)
MySQL 是进行内部联接;也就是说,您显示的查询是内部联接的一种实现。
来自docs:
innerjoin = False - 当为True时,加入的eager加载将使用内部联接 连接相关表而不是外连接。目的 这个选项严格地说是性能之一,作为内部连接 通常比外连接表现更好。此标志可以设置为 当关系通过多对一使用引用对象时为True 不可为空的本地外键,或者引用时的外键 一对一或保证有一个或至少一个的集合 一个条目。
关键点是inner join vs. outer join。语法无关紧要。
请注意,您的查询可以使用具有完全相同含义的inner join
句法形式转换为查询:
SELECT permissions.permissionid AS permissions_permissionid,
permissions.name AS permissions_name
FROM permissions
INNER JOIN users_permissions
ON permissions.permissionid = users_permissions.permissionid
WHERE ? = users_permissions.userid
ORDER BY permissions.name
MySQL通常会为这两种表单生成相同的执行计划。