go mysql教学_Go语言中mysql数据库操作(一)

数据的持久化是程序中必不可少的,所以编程语言中对数据库的操作是非常重要的一块,本文介绍Go语言对mysql数据库的操作。

基本操作

建立连接

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")

errDeal("连接数据库", err)

defer db.Close()

连接参数一般有以下几种

user@unix(/path/to/socket)/dbname?charset=utf8

user:password@tcp(localhost:5555)/dbname?charset=utf8

user:password@/dbname

user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname

增删改操作

// 插入数据---------------------方法1

result, err := db.Exec("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +

" VALUES(?,now(),?,?,?)", "admin", "127.0.0.1", "登录", "登录成功")

errDeal("插入数据", err)

// 查看返回信息

count, err := result.RowsAffected()

errDeal("查看插入数据条数", err)

fmt.Printf("插入数据条数:%d\n", count)

id, err := result.LastInsertId()

errDeal("查看最后插入数据的id", err)

fmt.Printf("最后插入数据的id:%d\n", id)

// 插入数据---------------------方法2,先创建一个预处理语句,再执行

stmt, err := db.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +

" VALUES(?,now(),?,?,?)")

result1, err1 := stmt.Exec("admin", "127.0.0.1", "登录", "登录成功")

errDeal("方法2插入数据", err1)

fmt.Println(result1.LastInsertId())

// 删除数据

result2, err := db.Exec("DELETE FROM admin_log WHERE id=?", 2014)

fmt.Println(result2.RowsAffected())

// 更新数据

result3, err := db.Exec("UPDATE admin_log SET log_ip=? WHERE id=?", "192.168.8.9", 2017)

fmt.Println(result3.RowsAffected())

单条数据查询

// 先定义存储查询结果的变量

var rid int

var username, time, ip, logType string

var desc, remark, spare interface{} // 如果字段中可能出现值为nil的情况,可以将变量申明为interface{}类型

err2 := db.QueryRow("SELECT id,admin_username,log_time,log_ip,log_type,log_desc,remark,spare" +

" FROM admin_log WHERE id=?", 2017).Scan(&rid, &username, &time, &ip, &logType, &desc, &remark, &spare) // 传入的是变量的指针

errDeal("查询单条数据", err2)

fmt.Printf("id=%d,username=%s,time=%s,ip=%s,logType=%s,desc=%s,remark=%v,spare=%v\n", rid, username, time, ip, logType, desc, remark, spare)

多条数据查询

// 查询多条数据

rows, err3 := db.Query("SELECT admin_username,log_time,log_ip,log_type,log_desc" +

" FROM admin_log WHERE id=? OR id=?", 2017, 2019)

errDeal("查询多条数据", err3)

// 对多条数据进行遍历

for rows.Next() {

err4 := rows.Scan(&username, &time, &ip, &logType, &desc)

errDeal("遍历多条数据", err4)

fmt.Printf("username=%s,time=%s,ip=%s,logType=%s,desc=%s\n", username, time, ip, logType, desc)

}

// 如果查询中不指定具体字段,使用*

rows, err33 := db.Query("SELECT *" +

" FROM admin_log WHERE id>?", 2017)

errDeal("查询多条数据", err33)

// 查询所有字段名,返回string切片

columes, err333 := rows.Columns()

errDeal("rows.Columns()方法调用", err333)

fmt.Printf("%T----%v\n", columes, columes)

var scanColumes = make([]interface{}, len(columes))

var values = make([]interface{}, len(columes))

for index, _ := range  scanColumes {

scanColumes[index] = &values[index]

}

for rows.Next() {

err4 := rows.Scan(scanColumes...)

errDeal("遍历多条数据", err4)

for i, val := range values {

if strings.EqualFold(judgeType(val), "[]uint8") {

fmt.Printf("%s(%T)==%s\t", columes[i], val, val)

} else {

fmt.Printf("%s(%T)==%v\t", columes[i], val, val)

}

}

fmt.Println()

}

事务

开启事务

// 开启事务,tx是从连接池中取出一个连接,在关闭之前都是使用这个连接,提交事务和回滚事务都是操作tx

tx, err5 := db.Begin()

errDeal("开启事务", err5)

_, err6 := tx.Exec("UPDATE admin_log SET log_desc=? WHERE id=?", "测试事务222", 2019)

//if err6 != nil {

if err6 == nil {

tx.Rollback() // 回滚

}

tx.Commit() // 提交

批量插入数据

// 批量数据插入

tx, err7 := db.Begin()

errDeal("数据批量插入,开启事务", err7)

insertValues := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功"},{"admin", "127.0.0.1", "删除", "删除数据"},{"admin", "127.0.0.1", "退出", "退出系统"}}

stmt, err8 := tx.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")

errDeal("数据批量插入,预处理", err8)

for _, val := range  insertValues {

_, err := stmt.Exec(val...)

if err != nil {

fmt.Printf("出现错误回滚,错误信息:%v", err)

tx.Rollback()

}

}

tx.Commit()

sqlx的使用及批量插入

xdb, err9 := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")

errDeal("sqlx连接数据库", err9)

txx, err10 := xdb.Beginx()

errDeal("sqlx开启事务", err10)

insertValuesx := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功X"},{"admin", "127.0.0.1", "删除", "删除数据X"},{"admin", "127.0.0.1", "退出", "退出系统X"}}

stmtx, err11 := txx.Preparex("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")

errDeal("数据批量插入,预处理", err11)

for _, val := range insertValuesx {

_, err := stmtx.Exec(val...)

if err != nil {

fmt.Printf("sqlx出现错误回滚,错误信息:%v", err)

txx.Rollback()

}

}

txx.Commit()

完整代码

package main

import (

"database/sql"

_"github.com/go-sql-driver/mysql" // 这里很重要,导入自己本地使用的数据库驱动,前面是下划线,否则会报错:sql: unknown driver "mysql" (forgotten import?)

"fmt"

"strings"

"github.com/jmoiron/sqlx"

)

func main() {

// 连接数据库,用户名:密码@协议(地址:端口)/数据库?参数=参数值,常用"用户名:密码@tcp(ip:端口)/数据库名?charset=字符集"

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")

errDeal("连接数据库", err)

defer db.Close()

//=========================================================================================增删改

// 插入数据---------------------方法1

result, err := db.Exec("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +

" VALUES(?,now(),?,?,?)", "admin", "127.0.0.1", "登录", "登录成功")

errDeal("插入数据", err)

// 查看返回信息

count, err := result.RowsAffected()

errDeal("查看插入数据条数", err)

fmt.Printf("插入数据条数:%d\n", count)

id, err := result.LastInsertId()

errDeal("查看最后插入数据的id", err)

fmt.Printf("最后插入数据的id:%d\n", id)

// 插入数据---------------------方法2,先创建一个预处理语句,再执行

stmt, err := db.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +

" VALUES(?,now(),?,?,?)")

result1, err1 := stmt.Exec("admin", "127.0.0.1", "登录", "登录成功")

errDeal("方法2插入数据", err1)

fmt.Println(result1.LastInsertId())

// 删除数据

result2, err := db.Exec("DELETE FROM admin_log WHERE id=?", 2014)

fmt.Println(result2.RowsAffected())

// 更新数据

result3, err := db.Exec("UPDATE admin_log SET log_ip=? WHERE id=?", "192.168.8.9", 2017)

fmt.Println(result3.RowsAffected())

//=============================================================================================查询

// 查询单条数据

// 先定义存储查询结果的变量

var rid int

var username, time, ip, logType string

var desc, remark, spare interface{} // 如果字段中可能出现值为nil的情况,可以将变量申明为interface{}类型

err2 := db.QueryRow("SELECT id,admin_username,log_time,log_ip,log_type,log_desc,remark,spare" +

" FROM admin_log WHERE id=?", 2017).Scan(&rid, &username, &time, &ip, &logType, &desc, &remark, &spare) // 传入的是变量的指针

errDeal("查询单条数据", err2)

fmt.Printf("id=%d,username=%s,time=%s,ip=%s,logType=%s,desc=%s,remark=%v,spare=%v\n", rid, username, time, ip, logType, desc, remark, spare)

// 查询多条数据

rows, err3 := db.Query("SELECT admin_username,log_time,log_ip,log_type,log_desc" +

" FROM admin_log WHERE id=? OR id=?", 2017, 2019)

errDeal("查询多条数据", err3)

// 对多条数据进行遍历

for rows.Next() {

err4 := rows.Scan(&username, &time, &ip, &logType, &desc)

errDeal("遍历多条数据", err4)

fmt.Printf("username=%s,time=%s,ip=%s,logType=%s,desc=%s\n", username, time, ip, logType, desc)

}

// 如果查询中不指定具体字段,使用*

rows, err33 := db.Query("SELECT *" +

" FROM admin_log WHERE id>?", 2017)

errDeal("查询多条数据", err33)

// 查询所有字段名,返回string切片

columes, err333 := rows.Columns()

errDeal("rows.Columns()方法调用", err333)

fmt.Printf("%T----%v\n", columes, columes)

var scanColumes = make([]interface{}, len(columes))

var values = make([]interface{}, len(columes))

for index, _ := range  scanColumes {

scanColumes[index] = &values[index]

}

for rows.Next() {

err4 := rows.Scan(scanColumes...)

errDeal("遍历多条数据", err4)

for i, val := range values {

if strings.EqualFold(checkType(val), "[]uint8") {

fmt.Printf("%s(%T)==%s\t", columes[i], val, val)

} else {

fmt.Printf("%s(%T)==%v\t", columes[i], val, val)

}

}

fmt.Println()

}

// ==================================================================================================事务

// 开启事务,tx是从连接池中取出一个连接,在关闭之前都是使用这个连接,提交事务和回滚事务都是操作tx

tx, err5 := db.Begin()

errDeal("开启事务", err5)

_, err6 := tx.Exec("UPDATE admin_log SET log_desc=? WHERE id=?", "测试事务222", 2019)

//if err6 != nil {

if err6 == nil {

tx.Rollback() // 回滚

}

tx.Commit() // 提交

// 批量数据插入

tx, err7 := db.Begin()

errDeal("数据批量插入,开启事务", err7)

insertValues := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功"},{"admin", "127.0.0.1", "删除", "删除数据"},{"admin", "127.0.0.1", "退出", "退出系统"}}

stmt, err8 := tx.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")

errDeal("数据批量插入,预处理", err8)

defer stmt.Close()

// 通过循环将每条SQL的参数写到目标表缓冲区。

for _, val := range  insertValues {

_, err := stmt.Exec(val...)

if err != nil {

fmt.Printf("出现错误回滚,错误信息:%v", err)

tx.Rollback()

}

}

tx.Commit()

// 使用sqlx批量数据插入

xdb, err9 := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")

errDeal("sqlx连接数据库", err9)

defer xdb.close()

txx, err10 := xdb.Beginx()

errDeal("sqlx开启事务", err10)

insertValuesx := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功X"},{"admin", "127.0.0.1", "删除", "删除数据X"},{"admin", "127.0.0.1", "退出", "退出系统X"}}

stmtx, err11 := txx.Preparex("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")

errDeal("数据批量插入,预处理", err11)

defer stmtx.Close()

// 通过循环将每条SQL的参数写到目标表缓冲区。

for _, val := range insertValuesx {

_, err := stmtx.Exec(val...)

if err != nil {

fmt.Printf("sqlx出现错误回滚,错误信息:%v", err)

txx.Rollback()

}

}

txx.Commit()

}

func errDeal(info string, err error) {

if err != nil {

panic(fmt.Sprintf("%s,错误信息:%v", info, err))

}

}

func checkType(val interface{}) string {

switch val.(type) {

case []uint8 :

return "[]uint8"

}

return ""

}

©著作权归作者所有:来自51CTO博客作者thao888的原创作品,如需转载,请注明出处,否则将追究法律责任

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值