我有两个结构:
type User struct {
Id uint32
First string
Last string
Adds []Address
}
type Address struct {
Id uint32
Location string
}
我有两张桌子:
create table user (
Id INT UNSIGNED NOT NULL AUTO_INCREMENT,
First VARCHAR(40) NULL,
Last VARCHAR(40) NULL,
PRIMARY KEY (Id)
);
create table address (
Id INT UNSIGNED NOT NULL AUTO_INCREMENT,
UserId INT UNSIGNED NOT NULL,
Location VARCHAR(400) NOT NULL,
FOREIGN KEY (UserId) REFERENCES user (Id),
PRIMARY KEY (Id)
);
"地址" 表与"用户" 表有一对多关系。 那么如何使用内部联接从这两个表中获取数据并将其保存在" user" struct instance ?
注意:没有 gorm 或其他 orm 库?
答案 0 :(得分:1)
使用单个查询和JOIN:
func GetUser(db *sql.DB, id int) (*User, error) {
rows, err := db.Query(`
SELECT
User.Id AS UserId,
User.First AS UserFirst,
User.Last AS UserLast,
Location.Id AS LocationId,
Location.Location AS LocationLocation
FROM User
LEFT JOIN Location ON
User.Id = Location.UserId
WHERE User.Id = ?
`, id)
if err != nil {
return nil, err
}
defer rows.Close()
var u *User
for rows.Next() {
if u == nil {
u = new(User)
}
var locationID sql.NullInt64
var location sql.NullString
err := rows.Scan(
&u.Id,
&u.First,
&u.Last,
&locationID,
&location,
)
if err != nil {
return nil, err
}
if locationID.Valid && location.Valid {
u.Adds = append(u.Adds, Address{
Id: uint32(locationID.Int64),
Location: location.String,
})
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return u, nil
}
或者,您可以使用两个查询,我认为这更清晰:
func GetUser(db *sql.DB, id int) (*User, error) {
u := new(User)
err := db.QueryRow(`
SELECT
Id,
First,
Last
FROM
user
WHERE Id = ?
`, id).Scan(
&u.Id,
&u.First,
&u.Last,
)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
rows, err := db.Query(`
SELECT
Id,
Location
FROM
addresses
WHERE UserId = ?
`, id)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var address Address
err := rows.Scan(
&address.Id,
&address.Location,
)
if err != nil {
return nil, err
}
u.Adds = append(u.Adds, address)
}
if err := rows.Err(); err != nil {
return nil, err
}
return u, nil
}