天天看點

sqlx的使用及注意點

前言

sqlx是基于Go内置database/sql包上的擴充,主要是簡化了sql的使用過程。sqlx的sql.DB, sql.TX, sql.Stmt等保持底層實作不變,是以可以很友善地從database/sql切換到sqlx。sqlx另外還提供了一些功能:

  • 可以将Rows内容解析至

    struct(支援内嵌)

    map

    slice

  • 命名參數支援
  • Get

    /

    Select

    可以快速将查詢結果轉為為

    struct

    /

    slice

使用

1. Open/Connect

Open可能僅校驗參數,而沒有與db間建立連接配接,要确認db是否可用,需要調用Ping。Connect則相當于Open+Ping。

使用如下:

db, err := sqlx.Open("postgres", "user=foo dbname=bar sslmode=disable")
    if err != nil {
        log.Fatalln(err)
    }
db, err := sqlx.Connect("mysql", "user:[email protected]:port?database")
    if err != nil {
        log.Fatalln(err)
    }
           

2. Queryx/QueryxContext/QueryRowx/QueryRowxContext

用于查詢多條/單條資料

與database/sql的Query/QueryxContext/QueryRow/QueryRowContext差別在于傳回的是*sqlx.Row

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

3. Exec

Exec執行sql語句而不傳回rows,主要用于insert、update、delete

4. 開啟事務

對應database/sql有Beginx、Preparex、Stmtx,帶有Must字首的方法,若發生錯誤則會panic

tx := db.MustBegin()
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "[email protected]")
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "[email protected]")
    tx.MustExec("INSERT INTO place (country, city, telcode) VALUES ($1, $2, $3)", "United States", "New York", "1")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Hong Kong", "852")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Singapore", "65")
    // Named queries can use structs, so if you have an existing struct (i.e. person := &Person{}) that you have populated, you can pass it in as &person
    tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "[email protected]"})
    tx.Commit()
           

5. Get/Select

sqlx提供了快速将查詢結果解析到struct、slice的方法,就是Get、Select。

Get用于查詢單條資料,Select則用于查詢多條資料,需要注意的是方法中的dest必須滿足要求,Get中不能為nil,Select中必須為slice。

tag注意:

使用struct需要注意,sqlx預設解析的tag為

"db"

,未設定tag,預設情況下是直接将field名轉換為

小寫

,是以預設情況下不滿足需求時,需要注意設定field的tag名,否則可能因為不比對而導緻資料處理失敗。

type Person struct {
    FirstName string `db:"first_name"`
    LastName  string `db:"last_name"`
    Email     string
}
people := []Person{}
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
jason, john := people[0], people[1]
jason = Person{}
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
fmt.Printf("%#v\n", jason)
           

如果存在null的情況,則field的類型必須設定為對應的

sql.Null*

類型(sql.NullBool、sql.NullInt64、sql.NullString等)

type Place struct {
    Country string
    City    sql.NullString
    TelCode int
}
// if you have null fields and use SELECT *, you must use sql.Null* in your struct
places := []Place{}
err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
if err != nil {
    fmt.Println(err)
    return
}
usa, singsing, honkers := places[0], places[1], places[2]

fmt.Printf("%#v\n%#v\n%#v\n", usa, singsing, honkers)
           

6. 命名參數支援

支援對sql中的命名參數解析支援,命名參數的格式為

:name

,執行時會主動擷取對應

name

的值。

// Named queries, using `:name` as the bindvar.  Automatic bindvar support
    // which takes into account the dbtype based on the driverName on sqlx.Open/Connect
    _, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, 
        map[string]interface{}{
            "first": "Bin",
            "last": "Smuth",
            "email": "[email protected]",
    })

    // Selects Mr. Smith from the database
    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:fn`, map[string]interface{}{"fn": "Bin"})

    // Named queries can also use structs.  Their bind names follow the same rules
    // as the name -> db mapping, so struct fields are lowercased and the `db` tag
    // is taken into consideration.
    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)
           

總結

本文簡單介紹了sqlx的使用及使用過程中的注意點,希望對大家有所幫助。

公衆号

鄙人剛剛開通了公衆号,專注于分享Go開發相關内容,望大家感興趣的支援一下,在此特别感謝。

sqlx的使用及注意點