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

在SQLAlchemy/Gino中,更新/插入语句能否返回关联查询列?

问题

我拥有Users和Tags两张数据表,希望在更新Tags表后,将Tags.created_by_user_id替换为左关联的Users.hash_id。

表定义如下:

class Tag(BaseClass):
    __tablename__ = "tags"
    ...
    created_by_user_id: Optional["UserId"] = db.Column(
        db.BigInteger,
        db.ForeignKey("users.id"),
        index=True,
    )

class User(BaseClass):
    __tablename__ = "users"
    ...
    id: Optional[int] = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
    hash_id: Optional[str] = db.Column(
        db.Text,
        index=True,
        server_default=FetchedValue(),
        nullable=False,
    )

我当前的解决方案是更新Tag后,通过更新语句返回的列再次查询Tag:

tag_int: int = (
            await ORMTag.update.values(**t)
            .where(
                and_(
                    ORMTag.hash_id == id,
                )
            )
            .returning(Tag.id)
            .gino.load(ColumnLoader(Tag.id))
            .first()
        )
tag: Tag = await db.select(
        [
            Tag.id,
            ...
            User.hash_id.label("created_by_user_id"),
        ]
    ).select_from(
        Tag.join(User, Tag.created_by_user_id == User.id, isouter=True)
    ).gino.first()

请问能否无需额外查询数据库,直接实现该需求?我已研究过with_expressions、query_expressions以及Gino子查询加载。


解决方案

可以直接在更新语句的returning子句中通过子查询获取关联的User.hash_id,无需二次查询数据库,示例代码如下:

updated_tag = await (
    ORMTag.update.values(**t)
    .where(ORMTag.hash_id == id)
    .returning(
        ORMTag.id,
        # 按需添加其他需要返回的Tag字段
        db.select([User.hash_id])
        .where(User.id == ORMTag.created_by_user_id)
        .label("created_by_user_id")
    )
    .gino.first()
)

说明

  • 子查询逻辑和你二次查询时的左关联逻辑一致,能直接匹配到对应用户的hash_id
  • 如果created_by_user_id为NULL,子查询会返回NULL,符合左关联的预期
  • 更新完成后,updated_tag会直接包含所有你需要的字段,包括替换后的created_by_user_id

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:32:54