如何在 sqlx 中读取外键

在我的数据库中,我有几个表:


团队


| 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 []Fixture

err := 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


任何帮助非常感谢


宝慕林4294392
浏览 147回答 1
1回答

largeQ

首先,没有办法直接做到这一点,例如,在struct上声明一些类型的字段,并让数据库驱动程序自动反序列化它们,因为两端的数据模型是根本不同的:数据库是关系的(假设这是因为你使用的是sqlx),而Go是面向对象的结构。因此,这将是ORM(对象关系映射,因此得名)的工作。但是假设您还不想使用ORM。XY其次,无论现有 FK 约束如何,您使用的 SQL 查询仅返回表中的数据。它不会神奇地返回其他数据。因此,您要么查询数据库两次,要么必须查询两个表:fixtureJOINSELECT   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_nameFROM  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)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go