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驱动相关推荐

  1. birt project mysql_birt中mysql驱动?

    请教个问题: birt中用的mysql驱动版本5.0.0,项目中用5.0.8,在查询时会抛出java.lang.ClassNotFoundException: com.mysql.jdbc.Drive ...

  2. spring boot中mysql驱动加载过程

    1.我们一般选择的Datasoure工具类  private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { "o ...

  3. golang中mysql建立连接超时时间timeout 测试

    本文测试连接mysql的超时时间. 这里的"连接"是建立连接的意思. 连接mysql的超时时间是通过参数timeout设置的. 1.建立连接超时测试 下面例子中,设置连接超时时间为 ...

  4. mysql pmt函数怎么用_在Golang中如何正确地使用database/sql包访问数据库

    本文记录了我在实际工作中关于数据库操作上一些小经验,也是新手入门golang时我认为一定会碰到问题,没有什么高大上的东西,所以希望能抛砖引玉,也算是对这个问题的一次总结.其实我也是一个新手,机缘巧合几 ...

  5. mysql驱动为什么自动加载_为什么JDBC中加载驱动要使用反射?

    原文链接:https://www.cnblogs.com/homejim/p/8076481.html 在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加 ...

  6. MYSQL,Oracle,SQL数据库在JSP中的驱动

    MYSQL,Oracle,SQL数据库在JSP中的驱动 datasource.url=jdbc:mysql://localhost:3306/bbscs6?useUnicode=true&ch ...

  7. go语言服务器连接mysql,golang中连接mysql数据库

    golang中连接mysql数据库,需要使用一个第三方类库github.com/go-sql-driver/mysql,在这个类库中就实现了mysql的连接池,并且只需要设置两个参数就可以实现 一般连 ...

  8. Java中使用mysql驱动连接mysql以及mysql的安装

    好久不见,随着Java课程的推进小编其实也在不断的学习之中,同时也遇到很多问题,下面就由小编为大伙们详细的说一下Java中使用mysql驱动连接mysql数据库以及mysql的安装以及使用数据库连接池 ...

  9. Golang中备份MYSQL数据库

    请注明出处:https://blog.csdn.net/qq_23179075/article/details/83306104 Golang中备份MYSQL数据库 package mainimpor ...

  10. eclipse中导入mysql 驱动包 jar包

    鼠标选中项目名→右键→新建→文件夹(文件夹名称:lib)→将下载好的mysql驱动包粘贴到lib文件夹中→鼠标选中lib文件夹下的mysql驱动包→右键→构建路径→添加至构建路径. 完成以上操作后会发 ...

最新文章

  1. 谈谈Backlog梳理活动
  2. 博客群发(2)--实现登陆
  3. 【转】企业开发的困境与变局
  4. 比特斯拉酒瓶更贵!小鹏汽车推出“金属麻将”:1999元
  5. php中提取%3cdiv,cmseasy getshell 0day
  6. python数据库去重复_python string 去重复数据库
  7. 报错注入是什么?一看你就明白了。报错注入原理+步骤+实战案例
  8. MongoDB常用操作命令大全
  9. 数据库实验八 数据库编程
  10. 想要定制专属AI声音?这是一份来自微软的保姆级攻略
  11. mybatis之 trim prefix=( suffix=)
  12. 比林志玲cute的katee
  13. Mybatis-Plus和Mybatis的区别
  14. 使用mysql查询显示行号
  15. 晶体三极管的放大原理
  16. 灵机一栋团队alpha冲刺 Ⅰ
  17. matlab seed函数_MATLAB中 STATE和SEED | 科研软件小站
  18. codefoces-A. Pens and Pencils
  19. 没戏,做不到,不存在的“不可能三角”
  20. Linux 下文件的查询与搜索

热门文章

  1. linux系统编译fortran,在Linux安装Fortran编译器
  2. [软件更新]gladder2.0.3.3
  3. 游戏编程之二 windows编程基础
  4. Bolt界面引擎中XLUE布局XML文件节点属性配置详解
  5. 详细解说“黑客”们热衷的热门抓鸡技术
  6. Ajax框架(14个开源的)
  7. Windows Builder 使用总结
  8. [渝粤题库]西北工业大学大学物理
  9. 冲击波病毒简介及解决方法
  10. dp在约会上是什么意思_dp是什么意思网络术语 饭圈为什么喜欢用缩写