Go 语言之 SQLX 高级操作 sqlx.In
sqlx.In 介绍
sqlx is a package for Go which provides a set of extensions on top of the excellent built-in database/sql package.
Illustrated guide to SQLX:http://jmoiron.github.io/sqlx/
sqlx:https://github.com/jmoiron/sqlx
"In" Queries
Because database/sql does not inspect your query and it passes your arguments directly to the driver, it makes dealing with queries with IN clauses difficult:- SELECT * FROM users WHERE level IN (?);
复制代码 When this gets prepared as a statement on the backend, the bindvar ? will only correspond to a single argument, but what is often desired is for that to be a variable number of arguments depending on the length of some slice, eg:- var levels = []int{4, 6, 7}rows, err := db.Query("SELECT * FROM users WHERE level IN (?);", levels)
复制代码 This pattern is possible by first processing the query with sqlx.In:- var levels = []int{4, 6, 7}query, args, err := sqlx.In("SELECT * FROM users WHERE level IN (?);", levels) // sqlx.In returns queries with the `?` bindvar, we can rebind it for our backendquery = db.Rebind(query)rows, err := db.Query(query, args...)
复制代码 What sqlx.In does is expand any bindvars in the query passed to it that correspond to a slice in the arguments to the length of that slice, and then append those slice elements to a new arglist. It does this with the ? bindvar only; you can use db.Rebind to get a query suitable for your backend.
普通批量插入数据,不使用 sqlx.In
- package main
- import (
- "database/sql"
- "fmt"
- "strings"
- "time"
- _ "github.com/go-sql-driver/mysql" // 匿名导入 自动执行 init()
- )
- var db *sql.DB
- func initMySQL() (err error) {
- //DSN (Data Source Name)
- dsn := "root:12345678@tcp(127.0.0.1:3306)/sql_test"
- // 注意:要初始化全局的 db 对象,不要新声明一个 db 变量
- db, err = sql.Open("mysql", dsn) // 只对格式进行校验,并不会真正连接数据库
- if err != nil {
- return err
- }
- // Ping 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接。
- err = db.Ping()
- if err != nil {
- fmt.Printf("connect to db failed, err: %v\n", err)
- return err
- }
- // 数值需要根据业务具体情况来确定
- db.SetConnMaxLifetime(time.Second * 10) // 设置可以重用连接的最长时间
- db.SetConnMaxIdleTime(time.Second * 5) // 设置连接可能处于空闲状态的最长时间
- db.SetMaxOpenConns(200) // 设置与数据库的最大打开连接数
- db.SetMaxIdleConns(10) // 设置空闲连接池中的最大连接数
- return nil
- }
- type User struct {
- Name string `db:"name"`
- Age int `db:"age"`
- }
- // BatchInsertUsers 批量插入数据
- func BatchInsertUsers(users []*User) error {
- valueStrings := make([]string, 0, len(users)) // 占位符 slice
- valueArgs := make([]interface{}, 0, len(users)*2) // 插入值 slice
- for _, u := range users {
- valueStrings = append(valueStrings, "(?, ?)")
- valueArgs = append(valueArgs, u.Name, u.Age) // 占位符与插入值 一一对应
- }
- // 拼接完整的SQL语句
- // Sprintf根据格式说明符进行格式化,并返回结果字符串。
- // Join将其第一个参数的元素连接起来以创建单个字符串。分隔字符串sep放置在结果字符串的元素之间。
- stmt := fmt.Sprintf("INSERT INTO user (name, age) VALUES %s", strings.Join(valueStrings, ","))
- // Exec执行查询而不返回任何行。参数用于查询中的任何占位符参数。
- result, err := db.Exec(stmt, valueArgs...)
- if err != nil {
- fmt.Printf("Error inserting user into database: %v \n", err)
- return err
- }
- var rows_affected int64
- rows_affected, err = result.RowsAffected() // 返回受更新、插入或删除影响的行数。并非每个数据库或数据库驱动程序都支持此功能。
- if err != nil {
- fmt.Printf("返回受更新、插入或删除影响的行数 failed, err: %v\n", err)
- return err
- }
- fmt.Println("受更新、插入或删除影响的行数: ", rows_affected)
- return nil
- }
- func main() {
- if err := initMySQL(); err != nil {
- fmt.Printf("connect to db failed, err: %v\n", err)
- }
- // 检查完错误之后执行,确保 db 不为 nil
- // Close() 用来释放数据库连接相关的资源
- // Close 将关闭数据库并阻止启动新查询。关闭,然后等待服务器上已开始处理的所有查询完成。
- defer db.Close()
- fmt.Println("connect to database success")
- // db.xx() 去使用数据库操作...
- // 批量插入数据
- users := []*User{
- {Name: "刘备", Age: 25},
- {Name: "关羽", Age: 30},
- {Name: "张飞", Age: 28},
- }
- err := BatchInsertUsers(users)
- if err != nil {
- fmt.Printf("Failed to batch insert users: %v", err)
- }
- }
复制代码 运行
[code]Code/go/mysql_demo via
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |