You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLAlchemy 1.4异步JOIN查询无法同时获取两张关联表数据问题

问题原因

scalars() 方法的设计逻辑就是仅提取结果行中第一个位置的实体/字段,当你在select()中传入多个实体时,每行查询结果是包含多个ORM实例的元组,调用scalars()会默认丢弃元组中除第一个外的其他数据,这就是你只能拿到单个表数据的核心原因。

解决方案

以下是两种常用的可行方案:

  • 方案1:直接调用结果集的all()方法获取完整行数据
    不需要加scalars()调用,直接从执行结果中取all(),每行返回的是对应select()参数顺序的ORM实例元组,可以直接解包使用:
    # 执行查询的语句保持不变
    stmt = select(Resource, UserResourceRole).join(UserResourceRole)
    result = await async_session.execute(stmt)
    # 直接调用all()获取完整行数据
    rows = result.all()
    # 遍历解包使用
    for resource, user_role in rows:
        print(resource.id, user_role.permission)
    
  • 方案2:通过ORM关系预加载关联数据(更符合ORM使用规范)
    先在你的Resource模型中定义和UserResourceRole的关联关系:
    from sqlalchemy.orm import relationship
    class Resource(Base):
        __tablename__ = "resource"
        # 原有字段定义保持不变...
        # 定义和中间表的关联关系
        user_roles = relationship("UserResourceRole", back_populates="resource")
    
    class UserResourceRole(Base):
        __tablename__ = "user_resource_role"
        # 原有字段定义保持不变...
        resource_id = Column(ForeignKey("resource.id"))
        resource = relationship("Resource", back_populates="user_roles")
    
    查询时使用joinedload预加载关联数据,查出来的Resource实例会直接携带对应的权限数据:
    from sqlalchemy.orm import joinedload
    
    stmt = select(Resource).join(Resource.user_roles).options(joinedload(Resource.user_roles))
    result = await async_session.execute(stmt)
    # 因为返回的第一个实体是Resource,可用scalars()提取,加unique()去重一对多关联产生的重复行
    resources = result.scalars().unique().all()
    # 直接访问关联权限即可
    for resource in resources:
        print(resource.id, [role.permission for role in resource.user_roles])
    
注意事项
  • 如果你的查询需要返回指定字段而非完整ORM实例,可以在select()中明确列出对应字段,同样直接用all()获取每行的字段值元组即可。
  • 异步场景下上述两种方案都完全兼容,不需要额外调整会话逻辑。

内容的提问来源于stack exchange,提问作者mlisthenewcool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 16:54:02