前言
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開發相關内容,望大家感興趣的支援一下,在此特别感謝。
