首页 文章

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

提问于
浏览
1

我有两个结构:

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

type Address struct {
    Id uint32
    Location string
}

我有两张 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" 表与 "user" 表有 one to many 关系 . 那么如何用 inner join 从这两个表中获取数据并将其保存在 "user" struct instance 中呢?

Note :没有 gorm 或其他 orm 库?

1 回答

  • 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
    }
    

相关问题