Go Mysql驱动
Golang中MYSQL驱动
- Mysql库https://github.com/go-sql-driver/mysql
- Go本身不提供具体数据库驱动,只提供驱动接口和管理。
- 各个数据库驱动需要第三方实现,并且注册到Go中的驱动管理中。
安装golang mysql drvier
go get github.com/go-sql-driver/mysql
代码中需要注册mysql数据库驱动,通过引入空白导入mysql包来完成。
为什么需要使用空白导入? 是因为需要执行mysql包的初始化代码(代码位于%GOPATH%/github.com/go-sql-driver/mysql/driver.go)
func init() {
sql.Register("mysql", &MySQLDriver{})
}
连接数据的DSN格式
username:password@protocol(address)/dbname?param=value
Prepared Statement
sql.Stmt支持预备表达式,可以用来优化SQL查询提高性能,减少SQL注入的风险, DB.Prepare()和Tx.Prepare()都提供了对于预备表达式的支持。
预处理的流程:
step1. 将sql分为2部分.命令部分和数据部分.
step2. 首先将命令部分发送给mysql服务器,mysql进行预处理.(如生成AST)
step3. 然后将数据部分发送给mysql服务器,mysql进行占位符替换.
step4. mysql服务器执行sql语句,把执行结果发送给客户端.
预处理的优势:
1.因为发送命令后,在mysql服务器端,就会将AST生成好,所以不需要对每一次值的更换都重新生成一次AST.对同样的数据不同的SQL来讲,只需生成1次AST,并缓存起来即可.
2.避免SQL注入.因为mysql知道再次发送过来的内容为”数据”,因此不会将这些数据解析为SQL,避免了SQL注入.
需要注意的点:
使用预处理进行查询操作时,不仅在defer时需要关闭结果集,而且还要关闭命令句柄,否则同样会占用连接,导致阻塞.
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) type User struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} func PrepareQuery(db *sql.DB, id int) {
stmt, err := db.Prepare("select id, name, age from user where id>?")
if err != nil {
panic(err)
} rows, err := stmt.Query(id)
if err != nil {
panic(err)
} defer stmt.Close()
defer rows.Close() for rows.Next(){
var user User
err := rows.Scan(&user.Id, &user.Name, &user.Age)
if err != nil {
panic(err)
}
fmt.Printf("user: %#v\n", user)
}
} func main() { dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} defer db.Close() PrepareQuery(db, ) }
Mysql创建表:
CREATE TABLE user (
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(20) DEFAULT '',
age int(2) DEFAULT '0',
PRIMARY KEY (id))
ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
数据库增删改查
insert
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Insert(db *sql.DB) {
name := "Vincent"
age := result, err := db.Exec("insert into user(name, age) values (?,?)", name, age)
if err != nil {
panic(err)
} id, err := result.LastInsertId()
if err != nil {
panic(err)
} affected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("last insert id:%d affect rows:%d\n", id, affected)
} func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("connect to db success!!!")
Insert(db)
}
delete
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Delete(db *sql.DB, id int) {
result, err := db.Exec("delete from user where id=?", id)
if err != nil {
panic(err)
} rowsAffected, err := result.RowsAffected()
if err != nil {
panic(err)
}
fmt.Printf("delect id:%d, affect rows:%d\n", id, rowsAffected)
} func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, _ := sql.Open("mysql", dns)
Delete(db, )
}
update
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Update(db *sql.DB) {
name := "Miles"
age :=
id := result, err := db.Exec("update user set name=?, age=? where id=?", name, age, id)
if err != nil {
panic(err)
} // RowsAffected returns the number of rows affected by an
// update, insert, or delete.
rowsAffected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("update id:%d, affect rows:%d\n", id, rowsAffected) } func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("connect to db success!!!")
Update(db)
}
query
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
"log"
) type User struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} // 单行查询,如果查询到多个结果,只返回第一行,查询不到结果就ErrNoRows错误。
func QueryRow(db *sql.DB) {
id:=
row := db.QueryRow("select id, name, age from user where id=?", id) var user User
err := row.Scan(&user.Id, &user.Name, &user.Age) if err == sql.ErrNoRows {
log.Printf("not found data of the id:%d",id)
} if err != nil {
panic(err)
} fmt.Printf("user: %#v\n", user)
} // 多行查询, 查询不到任何记录也不会报错。
func Query(db *sql.DB) {
id :=
rows, err := db.Query("select id, name, age from user where id>?", id)
if err != nil {
panic(err)
}
if err == sql.ErrNoRows {
log.Printf("not found data of id:%d\n", id)
return
}
defer rows.Close() for rows.Next() {
var user User
err := rows.Scan(&user.Id, &user.Name, &user.Age)
if err != nil {
panic(err)
}
fmt.Printf("user: %#v\n", user)
} } func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} fmt.Printf("connect to db success\n") //QueryRow(db) Query(db)
}
事务支持
事务(transaction)
- transaction, err := Db.Begin() 开启事务
- transaction.Exec() 执行事务
- transaction.Commit() 提交事务
- transaction.Rollback() 回滚事务
A. 事务的应用场景
1. 同时更新多个表
2. 同时更新多行数据
B. 事务的ACID
1. 原子性
2. 一致性
3. 隔离性
4. 持久性
需要注意的点:
1. 执行失败要回滚
2. 提交失败要回滚
package main import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
) func Transaction(db *sql.DB) { // 开启事务
tx, err := db.Begin() if err != nil {
panic(err)
} result, err := tx.Exec("insert into user(name, age)values(?,?)", "Jack", )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
} fmt.Println("result", result) exec, err := tx.Exec("update user set name=?, age=? where id=?", "Jack", , )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
fmt.Println("exec", exec) // 提交事务
err = tx.Commit() if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
} func main() { dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} Transaction(db)
}
Mysql日期时间类型报错
sql: Scan error on column index 1: unsupported Scan, storing driver.Value type []uint8 into type *time.Time
原因是在调用sql.Open()时没有将parseTime设置为True。加入parseTime即可修复问题:
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true")
Go Mysql驱动的更多相关文章
- python 3.5.2安装mysql驱动报错
python 3.5.2安装mysql驱动报错 python 3.5.2安装mysql驱动时出现如下异常: [root@localhost www]# pip install mysql-connec ...
- Go-MySQL-Driver:一个Go语言的轻量级极速的mysql驱动
Go语言的 database/sql 包的一个 MySQL驱动. 特性 轻量级与快速 原生Go语言,没有C绑定,只有纯Go 没有不安全的操作(类型转换等) 动态处理崩溃的连接 动态连接池 支持大于16 ...
- Ubuntu 16.04 - python3 安装mysql驱动
阿西吧,今天碰到一件特别蛋疼的事,给Ubuntu安装Python的MySQL驱动,驱动显示安装成功了 pip install mysql-connector 但是 在程序中导入,老是报错. Trace ...
- QT编译mysql驱动
一. 下载mysql C链接库 地址:http://dev.mysql.com/downloads/ 根据当前系统选择下载: 二. 安装下载好的mysql驱动文件 注意,一定要安装在不含有中文.空格以 ...
- centos7下编译qt的mysql驱动
在编译mysql驱动之前,首先要安装mysql,可以使用yum安装,这里将不再介绍. 在将qt和mysql都安装好之后,首先找到mysql的头文件以及他的共享库,我的mysql是使用yum安装的,头文 ...
- MySQL驱动阅读------Connection连接的建立,基于JDBC-----5.1.26
一般获取数据库连接的程序 Class.forName("com.mysql.jdbc.Driver"); final Connection connection = (Connec ...
- java mysql驱动
mysql驱动方式有三种, 1.第一种是先把jar包放在项目的目录下,通过添加jar包,是使用相对地址的,这样把项目复制到其它电脑也可以用 2.第二种方法是导入外部的jar包,是绝对地址,如果项目要复 ...
- Window下 Qt 编译MySQL驱动(居然用到了动态库格式转换工具)
一步步在Window下开发Qt 今天开始安装MySQL,看了些关于MySQL安装的博文,方法大致相同,但是遇到的细节问题各有不同,或者没有讲全面,下面来说说个人的安装过程及遇到的问题. 1.首先下载, ...
- Oozie安装时放置Mysql驱动包的总结(网上最全)
不多说,直接上干货! 对于在oozie里放置Mysql驱动包的总结 根据网上的参考以及我个人经验安装的使用 (1)放一份到$OOZIE_HOME/libext下 (是 mysql-connector- ...
- 关于mysql驱动包的in语句的bug
今天发现一个MySQL驱动包执行in语句的一个bug,也许会有很多人还不知道,那么跟大家分享一下. 驱动包版本:mysql-connector-java-5.1.36.jar 在使用dbutils执行 ...
随机推荐
- jQuery实现限制文本框的输入长度
jQuery限制文本框输入,包含粘贴. //限制文本框的输入长度 $(function () { $(document).on("keypress", ".txt-va ...
- poj 2125(最小割)
题目链接:http://poj.org/problem?id=2125 思路:将最小点权覆盖转化为最小割模型,于是拆点建图,将点i拆成i,i+n,其中vs与i相连,边容量为w[i]-,i+n与vt相连 ...
- MySQL右连接
1.语法:select 字段列表 from table1 别名1 right join table2 别名2 on 连接条件 [where 子句]
- Jmeter BeanShell 引用变量报错jmeter.util.BeanShellInterpreter: Error invoking bsh method: eval Parse error at line 14, column 181 : Error or number too big for integer
如果你通过CSV Data Set Config或者_StringFromFile函数来参数化你的请求,需要特别注意当参数为纯数字时,jmeter会默认将其识别成int型数据,说明jmeter并不是默 ...
- bootstrap获取总条目数
$('#table').on('load-success.bs.table', function () {alert($('#table').bootstrapTable('getOptions'). ...
- 巨蟒python全栈开发django1:自定义框架
今日大纲: 1.val和text方法的补充 2.信息收集卡用bootstrap实现 3.自定义web框架 4.http协议 5.自定义web框架2 今日内容详解: 1.val和text方法的补充 ht ...
- Python 通过字符串调用函数、接近属性
需求:传入的是函数名.属性名,想通过字符串调用函数,接近属性. 通过字符串接近.变动属性 变量:model_name, field_name # 获取 model model = AppConfig. ...
- Windows下批处理文件(.bat)的使用
cmd文件和bat文件的区别:在本质上两者没有区别,都是简单的文本编码方式,都可以用记事本创建.编辑和查看.两者所用的命令行代码也是共用的,只是cmd文件中允许使用的命令要比bat文件多.cmd文件只 ...
- JVM 指令讲解
挺有意思的 转载记录下 转载自 https://www.cnblogs.com/f1194361820/p/8524666.html 原作者: 房继诺 JVM 指令 1.Demo 2.Clas ...
- do while 宏定义如何使用?
#define verification(lhs,rhs,str) do { \ if (lhs == rhs) { \ std::cout << rang::style::bold &l ...