Go 1.17使用Sqlx关联同名字段表时ID被覆盖如何解决
问题根因
sqlx做结构体映射时,会按照查询返回的列顺序,匹配结构体字段的db标签(没有标签则匹配字段名小写)赋值,你使用SELECT *做联表查询时,两张表的id、title字段名重复,后返回的movie表字段值会覆盖Album结构体对应字段的值。
解决方案
两种常用方案可以解决这个问题:
方案1:显式指定查询字段,给嵌入结构体字段加别名
放弃SELECT *写法,明确列出需要查询的字段,跳过不需要的movie表id字段,同时给和Album重名的movie字段加movie.前缀别名,sqlx会自动将该类字段映射到内嵌的Movie结构体中,示例代码如下:albums := []Album{} sql := ` SELECT a.id, a.title, a.artist, a.price, a.movie_id, m.year, m.rent_number, m.title as "movie.title", m.author, m.editor, m.index, m.bib, m.ref, m.cat_1, m.cat_2 FROM album a INNER JOIN movie m ON m.id = a.movie_id ` if err := r.db.Select(&albums, sql); err != nil { // 错误处理逻辑 }这种方案不需要修改原有结构体定义,适合临时做联表查询的场景。
方案2:给内嵌结构体加
db前缀标签
先修改Album结构体,给内嵌的Movie字段加db标签指定统一前缀:type Album struct { ID string `json:"id"` Title string `json:"title"` Artist string `json:"artist"` Price float64 `json:"price"` MovieId int `json:"movie_id" db:"movie_id"` // 指定内嵌结构体所有字段的映射前缀 Movie movie.Movie `db:"movie_"` }写查询SQL时给所有movie表的字段加对应前缀的别名,同样跳过movie的id字段即可:
albums := []Album{} sql := ` SELECT a.id, a.title, a.artist, a.price, a.movie_id, m.year as movie_year, m.rent_number as movie_rent_number, m.title as movie_title, m.author as movie_author, m.editor as movie_editor, m.index as movie_index, m.bib as movie_bib, m.ref as movie_ref, m.cat_1 as movie_cat_1, m.cat_2 as movie_cat_2 FROM album a INNER JOIN movie m ON m.id = a.movie_id ` if err := r.db.Select(&albums, sql); err != nil { // 错误处理逻辑 }这种方案字段映射更清晰,适合多场景频繁使用该关联结构体查询的场景。
注意事项
联表查询时尽量不要使用SELECT *写法,显式指定字段不仅可以避免字段覆盖问题,也能减少不必要的字段查询,提升查询效率。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

