Go 语言之 SQLX 高级操作 sqlx.In

打印 上一主题 下一主题

主题 913|帖子 913|积分 2739

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:
  1. 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:
  1. 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:
  1. 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
  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         "strings"
  6.         "time"
  7.         _ "github.com/go-sql-driver/mysql" // 匿名导入 自动执行 init()
  8. )
  9. var db *sql.DB
  10. func initMySQL() (err error) {
  11.         //DSN (Data Source Name)
  12.         dsn := "root:12345678@tcp(127.0.0.1:3306)/sql_test"
  13.         // 注意:要初始化全局的 db 对象,不要新声明一个 db 变量
  14.         db, err = sql.Open("mysql", dsn) // 只对格式进行校验,并不会真正连接数据库
  15.         if err != nil {
  16.                 return err
  17.         }
  18.         // Ping 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接。
  19.         err = db.Ping()
  20.         if err != nil {
  21.                 fmt.Printf("connect to db failed, err: %v\n", err)
  22.                 return err
  23.         }
  24.         // 数值需要根据业务具体情况来确定
  25.         db.SetConnMaxLifetime(time.Second * 10) // 设置可以重用连接的最长时间
  26.         db.SetConnMaxIdleTime(time.Second * 5)  // 设置连接可能处于空闲状态的最长时间
  27.         db.SetMaxOpenConns(200)                 // 设置与数据库的最大打开连接数
  28.         db.SetMaxIdleConns(10)                  //  设置空闲连接池中的最大连接数
  29.         return nil
  30. }
  31. type User struct {
  32.         Name string `db:"name"`
  33.         Age  int    `db:"age"`
  34. }
  35. // BatchInsertUsers 批量插入数据
  36. func BatchInsertUsers(users []*User) error {
  37.         valueStrings := make([]string, 0, len(users))     // 占位符 slice
  38.         valueArgs := make([]interface{}, 0, len(users)*2) // 插入值 slice
  39.         for _, u := range users {
  40.                 valueStrings = append(valueStrings, "(?, ?)")
  41.                 valueArgs = append(valueArgs, u.Name, u.Age) // 占位符与插入值 一一对应
  42.         }
  43.         // 拼接完整的SQL语句
  44.         // Sprintf根据格式说明符进行格式化,并返回结果字符串。
  45.         // Join将其第一个参数的元素连接起来以创建单个字符串。分隔字符串sep放置在结果字符串的元素之间。
  46.         stmt := fmt.Sprintf("INSERT INTO user (name, age) VALUES %s", strings.Join(valueStrings, ","))
  47.         // Exec执行查询而不返回任何行。参数用于查询中的任何占位符参数。
  48.         result, err := db.Exec(stmt, valueArgs...)
  49.         if err != nil {
  50.                 fmt.Printf("Error inserting user into database: %v \n", err)
  51.                 return err
  52.         }
  53.         var rows_affected int64
  54.         rows_affected, err = result.RowsAffected() // 返回受更新、插入或删除影响的行数。并非每个数据库或数据库驱动程序都支持此功能。
  55.         if err != nil {
  56.                 fmt.Printf("返回受更新、插入或删除影响的行数 failed, err: %v\n", err)
  57.                 return err
  58.         }
  59.         fmt.Println("受更新、插入或删除影响的行数: ", rows_affected)
  60.         return nil
  61. }
  62. func main() {
  63.         if err := initMySQL(); err != nil {
  64.                 fmt.Printf("connect to db failed, err: %v\n", err)
  65.         }
  66.         // 检查完错误之后执行,确保 db 不为 nil
  67.         // Close() 用来释放数据库连接相关的资源
  68.         // Close 将关闭数据库并阻止启动新查询。关闭,然后等待服务器上已开始处理的所有查询完成。
  69.         defer db.Close()
  70.         fmt.Println("connect to database success")
  71.         // db.xx() 去使用数据库操作...
  72.         // 批量插入数据
  73.         users := []*User{
  74.                 {Name: "刘备", Age: 25},
  75.                 {Name: "关羽", Age: 30},
  76.                 {Name: "张飞", Age: 28},
  77.         }
  78.         err := BatchInsertUsers(users)
  79.         if err != nil {
  80.                 fmt.Printf("Failed to batch insert users: %v", err)
  81.         }
  82. }
复制代码
运行

[code]Code/go/mysql_demo via
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表