不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • GO基础

  • 面向对象

  • 并发编程

  • 常用库

  • 数据库操作

  • Beego框架

  • Beego商城

  • GIN框架

  • GIN论坛

    • 01.gin源码
    • 02.go内置sql模块
    • 03.sqlx库
    • 04.sqlx-In函数
      • 01.准备工作
        • 1.1 表结构
        • 1.2 结构体
      • 02.使用sqlx.In实现批量插入
        • 2.1 自己拼接语句实现批量插入
        • 2.2 使用sqlx.In实现批量插入
        • 2.3 使用NamedExec实现批量插入
      • 03.使用sqlx.In实现查询
        • 3.1 sqlx.In的查询示例
        • 3.2 in查询
        • 3.3 in查询和FINDINSET函数
    • 05.gin中使用zap日志
    • 06.gin优雅地关机
    • 07.大型WEB项目CLD分层
    • 08.web脚手架
    • 09.validator校验器
    • 10.雪花算法用户ID
    • 11.返回格式封装
    • 12.注册模块
    • 13.JWT
    • 14.登录模块
    • 15.社区接口开发
    • 16.认证中间件
    • 100.docker部署
    • 101.nginx部署
  • 微服务

  • 设计模式

  • Go
  • GIN论坛
xiaonaiqiang
2021-06-08
目录

04.sqlx-In函数

# 01.准备工作

# 1.1 表结构

CREATE TABLE `user` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(20) DEFAULT '',
    `age` INT(11) DEFAULT '0',
    PRIMARY KEY(`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
1
2
3
4
5
6

# 1.2 结构体

  • 定义一个user结构体,字段通过tag与数据库中user表的列一致。
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}
1
2
3
4

# 02.使用sqlx.In实现批量插入

# 2.1 自己拼接语句实现批量插入

  • 比较笨,但是很好理解。就是有多少个User就拼接多少个(?, ?)。
package main
import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"strings"
)

// 第一:建立连接
var DB *sqlx.DB

func initDB() (err error) {
	dsn := "root:chnsys@2016@tcp(127.0.0.1:3306)/sql_demo?charset=utf8mb4&parseTime=True"
	// 也可以使用MustConnect连接不成功就panic
	DB, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	DB.SetMaxOpenConns(2000)
	DB.SetMaxIdleConns(10)
	return
}

// 第二:定义结构体
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

// 第三:自行构造批量插入的语句
func BatchInsertUsers(users []*User) error {
	// 存放 (?, ?) 的slice
	valueStrings := make([]string, 0, len(users))
	// 存放values的slice
	valueArgs := make([]interface{}, 0, len(users) * 2)
	// 遍历users准备相关数据
	for _, u := range users {
		// 此处占位符要与插入值的个数对应
		valueStrings = append(valueStrings, "(?, ?)")
		valueArgs = append(valueArgs, u.Name)
		valueArgs = append(valueArgs, u.Age)
	}
	// 自行拼接要执行的具体语句
	stmt := fmt.Sprintf("INSERT INTO user (name, age) VALUES %s",
		strings.Join(valueStrings, ","))
	_, err := DB.Exec(stmt, valueArgs...)
	return err
}

// 第四:main函数调用
func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer DB.Close()
	u1 := User{Name: "wangwu", Age: 18}
	u2 := User{Name: "zhaoliu", Age: 28}
	u3 := User{Name: "sunqi", Age: 38}

	// 方法1
	users := []*User{&u1, &u2, &u3}
	err = BatchInsertUsers(users)
	if err != nil {
		fmt.Printf("BatchInsertUsers failed, err:%v\n", err)
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 2.2 使用sqlx.In实现批量插入

package main
import (
	"database/sql/driver"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// 第一:建立数据库连接
var DB *sqlx.DB
func initDB() (err error) {
	dsn := "root:chnsys@2016@tcp(127.0.0.1:3306)/sql_demo?charset=utf8mb4&parseTime=True"
	// 也可以使用MustConnect连接不成功就panic
	DB, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	DB.SetMaxOpenConns(2000)
	DB.SetMaxIdleConns(10)
	return
}

// 第二:定义结构体
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

// 第三:前提是需要我们的结构体实现driver.Valuer接口
// 前提是需要我们的结构体实现driver.Value 接口
func (u User) Value() (driver.Value, error) {
	return []interface{}{u.Name, u.Age}, nil
}

// 第四:使用sqlx.In实现批量插入代码如下
// 使用sqlx.In帮我们拼接语句和参数, 注意传入的参数是[]interface{}
func BatchInsertUsers2(users []interface{}) error {
	query, args, _ := sqlx.In(
		"INSERT INTO user (name, age) VALUES (?), (?), (?)",
		users..., // 如果arg实现了 driver.Valuer, sqlx.In 会通过调用 Value()来展开它
	)
	fmt.Println(query) // 查看生成的querystring
	fmt.Println(args)  // 查看生成的args
	_, err := DB.Exec(query, args...)
	return err
}

// 第五:mian函数调用
func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer DB.Close()
	u1 := User{Name: "wangwu", Age: 18}
	u2 := User{Name: "zhaoliu", Age: 28}
	u3 := User{Name: "sunqi", Age: 38}

	// 方法2
	users2 := []interface{}{u1, u2, u3}
	err = BatchInsertUsers2(users2)
	if err != nil {
		fmt.Printf("BatchInsertUsers2 failed, err:%v\n", err)
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 2.3 使用NamedExec实现批量插入

  • 推荐使用此方法

  • 注意 :该功能需1.3.1版本以上,并且1.3.1版本目前还有点问题,sql语句最后不能有空格和;,详见issues/690 (opens new window)。

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// 第一:建立数据库连接
var DB *sqlx.DB
func initDB() (err error) {
	dsn := "root:chnsys@2016@tcp(127.0.0.1:3306)/sql_demo?charset=utf8mb4&parseTime=True"
	// 也可以使用MustConnect连接不成功就panic
	DB, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	DB.SetMaxOpenConns(2000)
	DB.SetMaxIdleConns(10)
	return
}

// 第二:定义结构体
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

// 第三:使用NamedExec实现批量插入
func BatchInsertUsers3(users []*User) error {
	_, err := DB.NamedExec("INSERT INTO user (name, age) VALUES (:name, :age)", users)
	return err
}

// 第四:mian函数调用
func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer DB.Close()
	u1 := User{Name: "wangwu", Age: 18}
	u2 := User{Name: "zhaoliu", Age: 28}
	u3 := User{Name: "sunqi", Age: 38}

	// 方法3
	users3 := []*User{&u1, &u2, &u3}
	err = BatchInsertUsers3(users3)
	if err != nil {
		fmt.Printf("BatchInsertUsers3 failed, err:%v\n", err)
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 03.使用sqlx.In实现查询

# 3.1 sqlx.In的查询示例

  • 关于sqlx.In这里再补充一个用法,在sqlx查询语句中实现In查询和FIND_IN_SET函数。
  • 即实现SELECT * FROM user WHERE id in (3, 2, 1);
  • 和SELECT * FROM user WHERE id in (3, 2, 1) ORDER BY FIND_IN_SET(id, '3,2,1');

# 3.2 in查询

  • 查询id在给定id集合中的数据
package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// 第一:建立数据库连接
var DB *sqlx.DB
func initDB() (err error) {
	dsn := "root:chnsys@2016@tcp(127.0.0.1:3306)/sql_demo?charset=utf8mb4&parseTime=True"
	// 也可以使用MustConnect连接不成功就panic
	DB, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	DB.SetMaxOpenConns(2000)
	DB.SetMaxIdleConns(10)
	return
}

// 第二:定义结构体
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

// 第三:QueryByIDs 根据给定ID查询
func QueryByIDs(ids []int)(users []User, err error){
	// 动态填充id
	query, args, err := sqlx.In("SELECT name, age FROM user WHERE id IN (?)", ids)
	if err != nil {
		return
	}
	// sqlx.In 返回带 `?` bindvar的查询语句, 我们使用Rebind()重新绑定它
	query = DB.Rebind(query)
	err = DB.Select(&users, query, args...)
	return
}

// 第四:mian函数调用
func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer DB.Close()
	users , err := QueryByIDs([]int{7,5,6, 1})
	if err != nil {
		fmt.Printf("QueryByIDs failed, err:%v\n", err)
		return
	}
	for _, user := range users{
		fmt.Printf("user:%#v\n", user)
	}
}
/*
user:main.User{Name:"沙河小王子", Age:20}
user:main.User{Name:"zhaoliu", Age:28}
user:main.User{Name:"sunqi", Age:38}
user:main.User{Name:"wangwu", Age:18}
 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# 3.3 in查询和FIND_IN_SET函数

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"strings"
)

// 第一:建立数据库连接
var DB *sqlx.DB
func initDB() (err error) {
	dsn := "root:chnsys@2016@tcp(127.0.0.1:3306)/sql_demo?charset=utf8mb4&parseTime=True"
	// 也可以使用MustConnect连接不成功就panic
	DB, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	DB.SetMaxOpenConns(2000)
	DB.SetMaxIdleConns(10)
	return
}

// 第二:定义结构体
type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

// 第三:QueryAndOrderByIDs 按照指定id查询并维护顺序
func QueryAndOrderByIDs(ids []int)(users []User, err error){
	// 动态填充id
	strIDs := make([]string, 0, len(ids))
	for _, id := range ids {
		strIDs = append(strIDs, fmt.Sprintf("%d", id))
	}
	query, args, err := sqlx.In("SELECT name, age FROM user WHERE id IN (?) ORDER BY FIND_IN_SET(id, ?)", ids, strings.Join(strIDs, ","))
	if err != nil {
		return
	}

	// sqlx.In 返回带 `?` bindvar的查询语句, 我们使用Rebind()重新绑定它
	query = DB.Rebind(query)

	err = DB.Select(&users, query, args...)
	return
}

// 第四:mian函数调用
func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer DB.Close()

	// 1. 用代码去做排序
	// 2. 让MySQL排序
	fmt.Println("----")
	users ,err := QueryAndOrderByIDs([]int{7,5,6, 1})
	if err != nil {
		fmt.Printf("QueryByIDs failed, err:%v\n", err)
		return
	}
	for _, user := range users{
		fmt.Printf("user:%#v\n", user)
	}
}
/*
----
user:main.User{Name:"wangwu", Age:18}
user:main.User{Name:"zhaoliu", Age:28}
user:main.User{Name:"sunqi", Age:38}
user:main.User{Name:"沙河小王子", Age:20}
 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
上次更新: 2024/3/13 15:35:10
03.sqlx库
05.gin中使用zap日志

← 03.sqlx库 05.gin中使用zap日志→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式