yyz notes yyz notes
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

益章

可乐鸡翅
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • golang基础

  • golang高级

  • 常用组件

    • go操作mysql

      • mysql基础使用
      • mysql预处理
        • _什么是预处理?_
        • 为什么要预处理?
        • Go实现MySQL预处理
        • 示例
      • mysql sql注入问题
      • mysql事务
      • sqlx库使用指南
    • go操作redis

    • Zap日志库

    • 配置文件管理

  • gin

  • golang
  • 常用组件
  • go操作mysql
YiZhang-You
2023-05-24
目录

mysql预处理

# 2. mysql预处理

# 什么是预处理?

普通SQL语句执行过程:

  1. 客户端对SQL语句进行占位符替换得到完整的SQL语句。

  2. 客户端发送完整SQL语句到MySQL服务端

  3. MySQL服务端执行完整的SQL语句并将结果返回给客户端。

预处理执行过程:

  1. 把SQL语句分成两部分,命令部分与数据部分。

  2. 先把命令部分发送给MySQL服务端,MySQL服务端进行SQL预处理。

  3. 然后把数据部分发送给MySQL服务端,MySQL服务端对SQL语句进行占位符替换。

  4. MySQL服务端执行完整的SQL语句并将结果返回给客户端。

# 为什么要预处理?

  1. 优化MySQL服务器重复执行SQL的方法,可以提升服务器性能,提前让服务器编译,一次编译多次执行,节省后续编译的成本。

  2. 避免SQL注入问题。

# Go实现MySQL预处理

database/sql中使用下面的Prepare方法来实现预处理操作。

func (db *DB) Prepare(query string) (*Stmt, error)
1

Prepare方法会先将sql语句发送给MySQL服务端,返回一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令。

查询操作的预处理示例代码如下:

// PrepareQueryDemo 预处理查询示例
func PrepareQueryDemo() {
	sqlStr := "select id, name, age from user where id > ?"
	stmt, err := sqlClient.Db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err:%v\n", err)
		return
	}
	defer stmt.Close()
	rows, err := stmt.Query(0)
	if err != nil {
		fmt.Printf("query failed, err:%v\n", err)
		return
	}
	defer rows.Close()
	// 循环读取结果集中的数据
	for rows.Next() {
		var u user
		err := rows.Scan(&u.id, &u.name, &u.age)
		if err != nil {
			fmt.Printf("scan failed, err:%v\n", err)
			return
		}
		fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
	}
}
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

插入、更新和删除操作的预处理十分类似,这里以插入操作的预处理为例:

// PrepareInsertDemo 预处理插入示例
func PrepareInsertDemo(name string, age int) {
	sqlStr := "insert into user(name, age) values (?,?)"
	stmt, err := sqlClient.Db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err:%v\n", err)
		return
	}
	defer stmt.Close()
	_, err = stmt.Exec(name, age)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return
	}
	fmt.Println("insert success.")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 示例

operation.go

package operation

import (
	"fmt"
	sqlClient "main/utils"
)

// PrepareQueryDemo 预处理查询示例
func PrepareQueryDemo() {
	sqlStr := "select id, name, age from user where id > ?"
	stmt, err := sqlClient.Db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err:%v\n", err)
		return
	}
	defer stmt.Close()
	rows, err := stmt.Query(0)
	if err != nil {
		fmt.Printf("query failed, err:%v\n", err)
		return
	}
	defer rows.Close()
	// 循环读取结果集中的数据
	for rows.Next() {
		var u user
		err := rows.Scan(&u.id, &u.name, &u.age)
		if err != nil {
			fmt.Printf("scan failed, err:%v\n", err)
			return
		}
		fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
	}
}

// PrepareInsertDemo 预处理插入示例
func PrepareInsertDemo(name string, age int) {
	sqlStr := "insert into user(name, age) values (?,?)"
	stmt, err := sqlClient.Db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err:%v\n", err)
		return
	}
	defer stmt.Close()
	_, err = stmt.Exec(name, age)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return
	}
	fmt.Println("insert success.")
}
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

main.go

package main

import (
	"fmt"
	basicCURD "main/operation"
	sqlClient "main/utils"
)

func main() {

	// 一、连接mysql
	if err := sqlClient.InitDB(); err != nil { // 调用输出化数据库的函数
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	db := sqlClient.Db
	defer db.Close()
	fmt.Println("连接成功")

	// 二、基本增删改查
	//// 查询单条语句
	basicCURD.QueryRowDemo()
	//// 查询多态语句
	//basicCURD.QueryMultiRowDemo()
	//// 插入数据
	//basicCURD.InsertRowDemo("高起盛", 19)
	//// 更新数据
	//basicCURD.UpdateRowDemo(999, 1)
	//// 删除数据
	//basicCURD.DeleteRowDemo(7)

	// 三、预处理增删改查
	basicCURD.PrepareQueryDemo()
	basicCURD.InsertRowDemo("唐小虎", 19)
}

/*
连接成功

报错: init db failed,err:sql: unknown driver "mysql" (forgotten import?) 为安装mysql
*/
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
编辑 (opens new window)
mysql基础使用
mysql sql注入问题

← mysql基础使用 mysql sql注入问题→

最近更新
01
配置yun源
05-24
02
linux-配置python虚拟环境
05-24
03
linux文件目录管理
05-24
更多文章>
Theme by Vdoing | Copyright © 2023-2023 yizhang | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式