什么是预处理?

普通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预处理

Go中的

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

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

package main

import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql" // init()
) // Go连接MySQL示例 var db *sql.DB // db是一个连接池对象,每次操作会从连接池中取一个db对象来服务 func initDB() (err error) {
// 数据库信息
// 用户名:密码@tcp(ip:端口)/数据库的名字
dsn := "root:root@tcp(127.0.0.1:3306)/sql_test"
// 连接数据库
db, err = sql.Open("mysql", dsn) // 不会校验用户名和密码是否正确
if err != nil { // dsn格式不正确的时候会报错
return
}
err = db.Ping() // 尝试连接数据库
if err != nil {
return
}
db.SetMaxOpenConns(10) // 设置数据库连接池的最大连接数(连接池中只有10个连接,如果全部被占用,再来请求就会阻塞住)
db.SetMaxIdleConns(5) // 设置最大空闲连接数
return
} type user struct {
id int
name string
age int
} // 查询单个记录
func queryOne(id int) {
var u1 user //用来接收查询结果
// 1. 写查询单条记录的sql语句
sqlStr := `select id, name, age from user where id=?;` //?占位 下面的id
// 2. 执行并拿到结果
// 必须对rowObj对象调用Scan方法,因为该方法会释放数据库链接 // 从连接池里拿一个连接出来去数据库查询单条记录
db.QueryRow(sqlStr, id).Scan(&u1.id, &u1.name, &u1.age) //&u1.id, &u1.name, &u1.age初始化u1结构体对象(变量)
//row一行 // 打印结果
fmt.Printf("u1:%#v\n", u1)
} // 查询多条
func queryMore(n int) {
// 1. SQL语句
sqlStr := `select id, name, age from user where id > ?;`
// 2. 执行
rows, err := db.Query(sqlStr, n)
if err != nil {
fmt.Printf("exec %s query failed, err:%v\n", sqlStr, err)
return
}
// 3. 一定要关闭rows,才会释放连接(数据库的连接)
defer rows.Close()
// 4. 循环取值
for rows.Next() {
var u1 user
err := rows.Scan(&u1.id, &u1.name, &u1.age)
if err != nil {
fmt.Printf("scan failed,err:%v\n", err)
}
fmt.Printf("u1:%#v\n", u1)
}
} // 插入数据
func insert() {
// 1. 写SQL语句
sqlStr := `insert into user(name, age) values("图朝阳", 28)`
// 2. exec
ret, err := db.Exec(sqlStr) //exec执行(Python中的exec就是执行字符串代码的,返回值是None,eval有返回值)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
// 如果是插入数据的操作,能够拿到插入数据的id
id, err := ret.LastInsertId()
if err != nil {
fmt.Printf("get id failed,err:%v\n", err)
return }
fmt.Println("id:", id)
} // 更新操作
func updateRow(newAge int, id int) {
sqlStr := `update user set age=? where id > ?`
ret, err := db.Exec(sqlStr, newAge, id)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() //RowsAffected 受影响的行数
if err != nil {
fmt.Printf("get id failed,err:%v\n", err)
return
}
fmt.Printf("更新了%d行数据\n", n)
} // 删除
func deleteRow(id int) {
sqlStr := `delete from user where id=?`
ret, err := db.Exec(sqlStr, id)
if err != nil {
fmt.Printf("delete failed,err:%v\n", err)
return
}
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("get id failed,err:%v\n", err)
return
}
fmt.Printf("删除了%d行数据\n", n)
} // 预处理方式插入多条数据
func prepareInsert() {
sqlStr := `insert into user(name, age) values(?,?)`
stmt, err := db.Prepare(sqlStr) // 1.把SQL语句先发给MySQL预处理一下
if err != nil {
fmt.Printf("prepare failed ,err:%v\n", err)
return
}
defer stmt.Close()
// 后续只需要拿到stmt去执行一些操作
var m = map[string]int{
"六七强": 30,
"王相机": 32,
"天说": 72,
"白慧姐": 40,
}
for k, v := range m {
stmt.Exec(k, v) // 2.后续只需要传值
}
} func main() {
err := initDB()
if err != nil {
fmt.Printf("init DB failed, err:%v\n", err)
}
fmt.Println("连接数据库成功!")
// queryOne(2)
// queryMore(2)
// insert()
// updateRow(9000, 2)
// deleteRow(2)
prepareInsert()
}

Go实现MySQL事务

什么是事务?

事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元),同时这个完整的业务需要执行多次的DML(insert、update、delete)语句共同联合完成。A转账给B,这里面就需要执行两次update操作。

在MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行。

事务的ACID

通常事务必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

条件 解释
原子性 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

事务相关方法

Go语言中使用以下三个方法实现MySQL中的事务操作。 开始事务

func (db *DB) Begin() (*Tx, error)

提交事务

func (tx *Tx) Commit() error

回滚事务

func (tx *Tx) Rollback() error  

代码:

 package main

import (
"database/sql"
"fmt" _ "github.com/go-sql-driver/mysql" // init()
) var db *sql.DB // 是一个连接池对象 func initDB() (err error) {
// 数据库信息
// 用户名:密码@tcp(ip:端口)/数据库的名字
dsn := "root:root@tcp(127.0.0.1:3306)/sql_test"
// 连接数据库
db, err = sql.Open("mysql", dsn) // 不会校验用户名和密码是否正确
if err != nil { // dsn格式不正确的时候会报错
return
}
err = db.Ping() // 尝试连接数据库
if err != nil {
return
}
db.SetMaxOpenConns(10) // 设置数据库连接池的最大连接数
db.SetMaxIdleConns(5) // 设置最大空闲连接数
return
} type user struct {
id int
name string
age int
} func transactionDemo() {
// 1. 开启事务
tx, err := db.Begin()
if err != nil {
fmt.Printf("begin failed,err:%v\n", err)
return
}
// 执行多个SQL操作
sqlStr1 := `update user set age=age-2 where id=1`
sqlStr2 := `update xxx set age=age+2 where id=2`
// 执行SQL1
_, err = tx.Exec(sqlStr1)
if err != nil {
// 要回滚
tx.Rollback()
fmt.Println("执行SQL1出错啦,要回滚!")
return
}
// 执行SQL2
_, err = tx.Exec(sqlStr2)
if err != nil {
// 要回滚
tx.Rollback()
fmt.Println("执行SQL2出错啦,要回滚!")
return
}
// 上面两步SQL都执行成功,就提交本次事务
err = tx.Commit()
if err != nil {
// 要回滚
tx.Rollback()
fmt.Println("提交出错啦,要回滚!")
return
}
fmt.Println("事务执行成功!")
} func main() {
err := initDB()
if err != nil {
fmt.Printf("init DB failed, err:%v\n", err)
}
fmt.Println("连接数据库成功!")
transactionDemo()
}

  

Go_MySQL查询插入删除的更多相关文章

  1. 手把手教你使用C#操作SQLite数据库,新建数据库,创建表,插入,查询,删除,运算符,like

    目录: 一.新建项目,添加引用 二.创建数据库 三.创建表 四.插入数据  五.查询数据  六.删除数据  七.运算符 八.like语句 我的环境配置:windows 64,VS,SQLite(点击下 ...

  2. Hibernate插入、查询、删除操作 HQL

    Hibernate的所有的操作都是通过Session完成的. 基本步骤如下: 1:通过配置文件得到SessionFactory: SessionFactory sessionFactory=new C ...

  3. Splay的基本操作(插入/删除,查询)

    Splay的基本操作(插入/删除,查询) 概述 这是一棵二叉查找树 让频繁访问的节点尽量靠近根 将查询,插入等操作的点"旋转"至根 树的高度均摊为$log_n$ 变量 int ro ...

  4. TODO:MongoDB的查询更新删除总结

    TODO:MongoDB的查询更新删除总结 常用查询,条件操作符查询,< .<=.>.>=.!= 对应 MongoDB的查询操作符是$lt.$lte.$gt.$gte.$ne ...

  5. oracle_SQL 实验查询及删除重复记录 依据条件 (row)

    除数据库表中的重复记录 根据条件 ① 创建表准备数据 创建表 tab_test -- Create table create table TAB_TEST ( ID NUMBER, NAME NVAR ...

  6. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  7. django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  8. python Trie树和双数组TRIE树的实现. 拥有3个功能:插入,删除,给前缀智能找到所有能匹配的单词

    #coding=utf- #字典嵌套牛逼,别人写的,这样每一层非常多的东西,搜索就快了,树高26.所以整体搜索一个不关多大的单词表 #还是O(). ''' Python 字典 setdefault() ...

  9. [LeetCode] Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

随机推荐

  1. P1268 树的重量【构造】

    题目描述 树可以用来表示物种之间的进化关系.一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题是,根据物种之间的距离,重构相应的“进化树 ...

  2. 为什么重写equals方法,还必须要重写hashcode方法

    一.equals方法和hashcode的关系 根据Object.hashCode的通用约定: 如果两个对象相同(equals方法返回true),那么hashcode也相等.(图1) 如果两个对象的ha ...

  3. ASP.NET常用内置对象(二)Response

    response翻译为中文:响应. 将数据作为请求的结果从服务器发送到客户浏览器中,并提供有关响应的消息.它可用来在页面中输出数据,在页面中跳转,还可以传递各个页面的参数. Response对象是Sy ...

  4. python3练习100题——050

    题目:输出一个随机数. 程序分析:使用 random 模块. import random print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数 pri ...

  5. Extreme Learning Machine

    Extreme Learning Machine 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. ELM 2004年南洋理工大学黄广斌提出了ELM ...

  6. php 文件追加写入

    //追加写入 file_put_contents('xml.text',json_encode($postObj,JSON_FORCE_OBJECT).PHP_EOL,FILE_APPEND);

  7. 【巨杉数据库SequoiaDB】巨杉数据库荣获《金融电子化》“金融科技创新奖”

    巨杉助力金融科技创新 2019年12月19日,由<金融电子化>杂志社主办.北京金融科技产业联盟协办的“2019中国金融科技年会暨第十届金融科技及服务优秀创新奖颁奖典礼”在京成功召开.来自金 ...

  8. python xlrd 模块(获取Excel表中数据)

    python xlrd 模块(获取Excel表中数据) 一.安装xlrd模块   到python官网下载http://pypi.python.org/pypi/xlrd模块安装,前提是已经安装了pyt ...

  9. Appium+Python移动端(Android)自动化测试环境搭建

    一.安装JDK 下载好jdk安装包后直接下一步直至安装完成即可,安装完JDK后配置环境变量 :计算机→属性→高级系统设置→高级→环境变量: 系统变量→新建 JAVA_HOME 变量 变量值填写jdk的 ...

  10. C++——指针5

    8.2 指向类的静态成员的指针 对类的静态成员的访问不依赖于对象,可以用普通的指针来指向和访问. //通过指针访问类的静态数据成员 #include <iostream> using na ...