douying9296 2018-01-25 17:17
浏览 587
已采纳

如何从MySQL中具有一对多关系的两个表中获取数据?

I have two struct:

type User struct {
    Id uint32
    First string
    Last string
    Adds []Address
}

type Address struct {
    Id uint32
    Location string
}

And i have two table:

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)
);

"address" table has one to many relationship with "user" table. so how can i fetch data from these two table with inner join and save it in "user" struct instance?

Note: Without gorm or other orm library?

  • 写回答

1条回答 默认 最新

  • doushang1778 2018-01-25 17:28
    关注

    Using a single query and a 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
    }
    

    Alternatively, you can use two queries, which is cleaner in my opinion:

    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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Pwm双极模式H桥驱动控制电机
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题