为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 sqlx 中读取外键

如何在 sqlx 中读取外键

Go
宝慕林4294392 2022-08-24 11:19:42
在我的数据库中,我有几个表:团队| Field | Type    || ----- | ------- || ID    | int     || Name  | varchar |夹具| Field | Type || ----- | ---- || ID    | int  || Home  | int  || Away  | int  |也许很明显,和 列是 s 的外键。HomeAwayTeam在Go中,我将其定义为以下类型:type Team struct {  ID   int64  `json:"id" db:"id"`  Name string `json:"name" db:"name"`}type Fixture struct {  ID   int64 `json:"id" db:"id"`  Home int64 `json:"home" db:"home"`  Away int64 `json:"away" db:"away"`}我希望能够从数据库中读取一段夹具,如下所示:var fs []Fixtureerr := sqlx.DB.SelectContext(ctx, &fs, `SELECT * FROM fixture`)但这会导致错误:Scan error on column index 2, name "home": unsupported Scan, storing driver.Value type int64 into type *teams.Team我在这里读过关于嵌入的内容,但无法真正看到这有帮助,因为两者和同一类型,所以会有命名冲突。HomeAway任何帮助非常感谢
查看完整描述

1 回答

?
largeQ

TA贡献2039条经验 获得超8个赞

首先,没有办法直接做到这一点,例如,在struct上声明一些类型的字段,并让数据库驱动程序自动反序列化它们,因为两端的数据模型是根本不同的:数据库是关系的(假设这是因为你使用的是sqlx),而Go是面向对象的结构。因此,这将是ORM(对象关系映射,因此得名)的工作。但是假设您还不想使用ORM。XY


其次,无论现有 FK 约束如何,您使用的 SQL 查询仅返回表中的数据。它不会神奇地返回其他数据。因此,您要么查询数据库两次,要么必须查询两个表:fixtureJOIN


SELECT 

  f.id, 

  t1.id as home_team_id, 

  t1.name as home_team_name,

  t2.id as away_team_id,

  t2.name as away_team_name

FROM

  fixture f

  JOIN team t1 ON t1.id = f.home

  JOIN team t2 ON t2.id = f.away

请注意有助于区分列名的别名。这将返回必要的数据字段。现在,您可以使用第三个桥接结构来正确扫描从数据库获取的行,并使用它初始化您的主结构:as


    // Here I'm using (a slice of) anonymous structs, 

    // but you can declare a named one instead.

    bridge := []struct {

        FixtureId    int64  `db:"id"`

        HomeTeamId   int64  `db:"home_team_id"`

        HomeTeamName string `db:"home_team_name"`

        AwayTeamId   int64  `db:"away_team_id"`

        AwayTeamName string `db:"away_team_name"`

    }{}

    err := db.SelectContext(ctx, &bridge, query)

    if err != nil {

        // handle err...

    }

    mystructs := make([]Fixture, len(bridge))

    for i, b := range bridge {

        mystructs[i] = Fixture{

            ID: b.FixtureId,

            Home: Team{

                ID:   b.HomeTeamId,

                Name: b.HomeTeamName,

            },

            Away: Team{

                ID:   b.AwayTeamId,

                Name: b.AwayTeamName,

            },

        }

    }

其他不太方便的替代方案是:


用于获取结果并循环访问它,初始化结构。(记得在完成后关闭,释放资源)sqlx.Queryx(ctx, query)*sqlx.RowsFixtureRows

让父结构实现(示例Fixturesql.Scanner)


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 146 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号