2

我正在使用 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 查询以匹配当前系统中的查询。我正在尝试从迁移oursqlsqlalchemy orm.

4

1 回答 1

4

MySQL正在进行内部连接;也就是说,您显示的查询是内连接的一种实现。

文档

innerjoin=False – 当为 True 时,加入的渴望加载将使用内部联接而不是外部联接来联接相关表。此选项的目的严格来说是性能之一,因为内连接通常比外连接执行得更好。当关系使用不可为空的本地外键通过多对一引用对象时,或者当引用是一对一的或保证具有一个或至少一个的集合时,可以将此标志设置为 True一个条目。

关键点是内部联接与外部联接。语法无关紧要。

请注意,您的查询可以使用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 通常会为这两种形式生成相同的执行计划。

于 2012-05-03T19:31:56.913 回答