복붙노트

[SQL] 나는 구조체로 데이터베이스 행을 변환하려면 어떻게

SQL

나는 구조체로 데이터베이스 행을 변환하려면 어떻게

하자 내가 구조체를 말한다 :

type User struct {
    Name  string
    Id    int
    Score int
}

그리고 동일한 스키마와 데이터베이스 테이블. 구조체에 데이터베이스 행을 구문 분석하는 가장 쉬운 방법은 무엇입니까? 나는 아래 답변을 추가했지만 나는 확실히 그것을 최고의 하나 아니에요.

해결법

  1. ==============================

    1.이동 패키지 테스트는 종종 일을하는 방법에 대한 단서를 제공한다. 예를 들어, 데이터베이스 / SQL / sql_test.go,

    이동 패키지 테스트는 종종 일을하는 방법에 대한 단서를 제공한다. 예를 들어, 데이터베이스 / SQL / sql_test.go,

    func TestQuery(t *testing.T) {
        /* . . . */
        rows, err := db.Query("SELECT|people|age,name|")
        if err != nil {
                t.Fatalf("Query: %v", err)
        }
        type row struct {
                age  int
                name string
        }
        got := []row{}
        for rows.Next() {
                var r row
                err = rows.Scan(&r.age, &r.name)
                if err != nil {
                        t.Fatalf("Scan: %v", err)
                }
                got = append(got, r)
        }
        /* . . . */
    }
    
    func TestQueryRow(t *testing.T) {
        /* . . . */
        var name string
        var age int
        var birthday time.Time
        err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
        /* . . . */
    }
    

    어느, 귀하의 질문에 대한 구조에 행을 조회, 같은 것으로 변환합니다 :

    var row struct {
        age  int
        name string
    }
    err = db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&row.age, &row.name)
    

    나는 당신의 솔루션과 유사한 그 모습을 알고 있지만 해결책을 찾기 위해 방법을 보여하는 것이 중요합니다.

  2. ==============================

    2.나는 github.com/jmoiron/sqlx하는 것이 좋습니다.

    나는 github.com/jmoiron/sqlx하는 것이 좋습니다.

    의 README에서 :

    추가 정보는 구조체에 행을 스캔 보여주는 코드를 포함합니다 :

    type Place struct {
        Country       string
        City          sql.NullString
        TelephoneCode int `db:"telcode"`
    }
    // Loop through rows using only one struct
    place := Place{}
    rows, err := db.Queryx("SELECT * FROM place")
    for rows.Next() {
        err := rows.StructScan(&place)
        if err != nil {
            log.Fatalln(err)
        } 
        fmt.Printf("%#v\n", place)
    }
    

    우리가 수동으로 구조체의 필드에 각 열을 매핑해야하지 않습니다. SQLX는 구조체 데이터베이스 컬럼 필드뿐만 아니라 태그 (위의 장소 구조체의 TelephoneCode 필드를 참고)을 사용하여 데이터베이스 열을 지정 할 수있는 몇 가지 기본 매핑을 가지고있다. 당신은 문서에 그에 대한 자세한 내용을보실 수 있습니다.

  3. ==============================

    3.여기 한 가지 방법입니다 - 단지 수동으로 스캔 함수에서 구조체의 모든 값을 할당합니다.

    여기 한 가지 방법입니다 - 단지 수동으로 스캔 함수에서 구조체의 모든 값을 할당합니다.

    func getUser(name string) (*User, error) {
        var u User
        // this calls sql.Open, etc.
        db := getConnection()
        // note the below syntax only works for postgres
        err := db.QueryRow("SELECT * FROM users WHERE name = $1", name).Scan(&u.Id, &u.Name, &u.Score)
        if err != nil {
            return &User{}, err
        } else {
            return &u, nil
        }
    }
    
  4. ==============================

    4.

    rows, err := connection.Query("SELECT `id`, `username`, `email` FROM `users`")
    
    if err != nil {
        panic(err.Error())
    }
    
    for rows.Next() {
        var user User
    
        if err := rows.Scan(&user.Id, &user.Username, &user.Email); err != nil {
            log.Println(err.Error())
        }
    
        users = append(users, user)
    }
    

    전체 예

  5. ==============================

    5.단지에 대한 패키지가있다 : sqlstruct은

    단지에 대한 패키지가있다 : sqlstruct은

    불행하게도, 마지막으로 나는 그것이 포함 된 구조체를 지원하지 않았다 확인 (자신을 쉽게 구현할 수 있습니다 - 내가 몇 시간 만에 프로토 타입을했다).

    그냥 sqlstruct에 대한 변경 사항을 커밋

  6. ==============================

    6.사용하다 : 이동 - 모델 - MySQL의 sqlbuilder

    사용하다 : 이동 - 모델 - MySQL의 sqlbuilder

    val, err = m.ScanRowType(row, (*UserTb)(nil))
    

    또는 전체 코드

    import (
        "database/sql"
        "fmt"
    
        lib "github.com/eehsiao/go-models-lib"
        mysql "github.com/eehsiao/go-models-mysql"
    )
    
    // MyUserDao : extend from mysql.Dao
    type MyUserDao struct {
        *mysql.Dao
    }
    
    // UserTb : sql table struct that to store into mysql
    type UserTb struct {
        Name       sql.NullString `TbField:"Name"`
        Id         int            `TbField:"Id"`
        Score      int            `TbField:"Score"`
    }
    
    // GetFirstUser : this is a data logical function, you can write more logical in there
    // sample data logical function to get the first user
    func (m *MyUserDao) GetFirstUser() (user *User, err error) {
    
        m.Select("Name", "Id", "Score").From("user").Limit(1)
        fmt.Println("GetFirstUser", m.BuildSelectSQL().BuildedSQL())
        var (
            val interface{}
            row *sql.Row
        )
    
        if row, err = m.GetRow(); err == nil {
            if val, err = m.ScanRowType(row, (*UserTb)(nil)); err == nil {
                u, _ := val.(*UserTb)
    
                user = &User{
                    Name:       lib.Iif(u.Name.Valid, u.Nae.String, "").(string),
                    Id:         u.Id,
                    Score:      u.Score,
                }
            }
        }
        row, val = nil, nil
    
        return
    }
    
  7. ==============================

    7.여기에 단지에 대한 라이브러리입니다 : scany.

    여기에 단지에 대한 라이브러리입니다 : scany.

    당신은 그런 식으로 사용할 수 있습니다 :

    type User struct {
        Name  string
        Id    int
        Score int
    }
    
    // db is your *sql.DB instance
    // ctx is your current context.Context instance
    
    // Use sqlscan.Select to query multiple records.
    var users []*User
    sqlscan.Select(ctx, db, &users, `SELECT name, id, score FROM users`)
    
    // Use sqlscan.Get to query exactly one record.
    var user User
    sqlscan.Get(ctx, db, &user, `SELECT name, id, score FROM users WHERE id=123`)
    

    그것은 잘 문서화와 작업하기 쉽습니다.

    면책 조항 :이 라이브러리의 저자입니다.

  8. from https://stackoverflow.com/questions/17265463/how-do-i-convert-a-database-row-into-a-struct by cc-by-sa and MIT license