Golang中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 mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)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 Usererr := 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(127.0.0.1:3306)/golang"db, err := sql.Open("mysql", dns)if err != nil {panic(err)}defer db.Close()PrepareQuery(db, 0)
}
Mysql创建表:
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) DEFAULT '',
`age` INT(2) DEFAULT 0,
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
数据库增删改查
insert
package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)func Insert(db *sql.DB) {name := "Vincent"age := 18result, 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(127.0.0.1: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 mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)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(127.0.0.1:3306)/golang"db, _ := sql.Open("mysql", dns)Delete(db, 2)
}
update
package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)func Update(db *sql.DB) {name := "Miles"age := 88id := 3result, 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(127.0.0.1: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 mainimport ("database/sql""fmt""log"_ "github.com/go-sql-driver/mysql"
)type User struct {Id int `db:"id"`Name string `db:"name"`Age int `db:"age"`
}// 单行查询,如果查询到多个结果,只返回第一行,查询不到结果就ErrNoRows错误。
func QueryRow(db *sql.DB) {id := 1row := db.QueryRow("select id, name, age from user where id=?", id)var user Usererr := 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 := 0rows, 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 Usererr := 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(127.0.0.1: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 mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)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", 98)if err != nil {// 失败回滚tx.Rollback()panic(err)}fmt.Println("result", result)exec, err := tx.Exec("update user set name=?, age=? where id=?", "Jack", 98, 1)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(127.0.0.1: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")
Golang中MYSQL驱动相关推荐
- birt project mysql_birt中mysql驱动?
请教个问题: birt中用的mysql驱动版本5.0.0,项目中用5.0.8,在查询时会抛出java.lang.ClassNotFoundException: com.mysql.jdbc.Drive ...
- spring boot中mysql驱动加载过程
1.我们一般选择的Datasoure工具类 private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { "o ...
- golang中mysql建立连接超时时间timeout 测试
本文测试连接mysql的超时时间. 这里的"连接"是建立连接的意思. 连接mysql的超时时间是通过参数timeout设置的. 1.建立连接超时测试 下面例子中,设置连接超时时间为 ...
- mysql pmt函数怎么用_在Golang中如何正确地使用database/sql包访问数据库
本文记录了我在实际工作中关于数据库操作上一些小经验,也是新手入门golang时我认为一定会碰到问题,没有什么高大上的东西,所以希望能抛砖引玉,也算是对这个问题的一次总结.其实我也是一个新手,机缘巧合几 ...
- mysql驱动为什么自动加载_为什么JDBC中加载驱动要使用反射?
原文链接:https://www.cnblogs.com/homejim/p/8076481.html 在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加 ...
- MYSQL,Oracle,SQL数据库在JSP中的驱动
MYSQL,Oracle,SQL数据库在JSP中的驱动 datasource.url=jdbc:mysql://localhost:3306/bbscs6?useUnicode=true&ch ...
- go语言服务器连接mysql,golang中连接mysql数据库
golang中连接mysql数据库,需要使用一个第三方类库github.com/go-sql-driver/mysql,在这个类库中就实现了mysql的连接池,并且只需要设置两个参数就可以实现 一般连 ...
- Java中使用mysql驱动连接mysql以及mysql的安装
好久不见,随着Java课程的推进小编其实也在不断的学习之中,同时也遇到很多问题,下面就由小编为大伙们详细的说一下Java中使用mysql驱动连接mysql数据库以及mysql的安装以及使用数据库连接池 ...
- Golang中备份MYSQL数据库
请注明出处:https://blog.csdn.net/qq_23179075/article/details/83306104 Golang中备份MYSQL数据库 package mainimpor ...
- eclipse中导入mysql 驱动包 jar包
鼠标选中项目名→右键→新建→文件夹(文件夹名称:lib)→将下载好的mysql驱动包粘贴到lib文件夹中→鼠标选中lib文件夹下的mysql驱动包→右键→构建路径→添加至构建路径. 完成以上操作后会发 ...
最新文章
- 谈谈Backlog梳理活动
- 博客群发(2)--实现登陆
- 【转】企业开发的困境与变局
- 比特斯拉酒瓶更贵!小鹏汽车推出“金属麻将”:1999元
- php中提取%3cdiv,cmseasy getshell 0day
- python数据库去重复_python string 去重复数据库
- 报错注入是什么?一看你就明白了。报错注入原理+步骤+实战案例
- MongoDB常用操作命令大全
- 数据库实验八 数据库编程
- 想要定制专属AI声音?这是一份来自微软的保姆级攻略
- mybatis之 trim prefix=( suffix=)
- 比林志玲cute的katee
- Mybatis-Plus和Mybatis的区别
- 使用mysql查询显示行号
- 晶体三极管的放大原理
- 灵机一栋团队alpha冲刺 Ⅰ
- matlab seed函数_MATLAB中 STATE和SEED | 科研软件小站
- codefoces-A. Pens and Pencils
- 没戏,做不到,不存在的“不可能三角”
- Linux 下文件的查询与搜索
热门文章
- linux系统编译fortran,在Linux安装Fortran编译器
- [软件更新]gladder2.0.3.3
- 游戏编程之二 windows编程基础
- Bolt界面引擎中XLUE布局XML文件节点属性配置详解
- 详细解说“黑客”们热衷的热门抓鸡技术
- Ajax框架(14个开源的)
- Windows Builder 使用总结
- [渝粤题库]西北工业大学大学物理
- 冲击波病毒简介及解决方法
- dp在约会上是什么意思_dp是什么意思网络术语 饭圈为什么喜欢用缩写