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