连接mysql数据库
连接mysql需要导入musql驱动github.com/go-sql-driver/mysql和go内置的sql包database/sql。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql" // 并不直接使用,只用它的init
)
func main() {
// 获取数据库连接,返回值d是一个连接池指针
d, err := sql.Open("mysql", "root:666666@tcp(127.0.0.1:3306)/exercise")
if err != nil {
fmt.Println(err)
return
}
// 判断数据库是否连接成功
err2 := d.Ping()
if err2 != nil {
fmt.Println(err2)
return
}
// 关闭数据库连接
defer d.Close()
fmt.Println("连接成功")
}
操作数据库
查询
查询单行
// 查询单个数据
func query(id int) {
sqlStr := "select id,name,age from user where id=?"
// 不预处理查询单个
//db.QueryRow("select id name age from user where id=1")
// 预处理 使用预处理可以避免自己拼接sql语句导致sql注入等问题,且可以提高效率
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("query faild, err:%v\n", err)
return
}
var u user
err2 := stmt.QueryRow(id).Scan(&u.id, &u.name, &u.age)
if err2 != nil {
fmt.Printf("query faild, err:%v\n", err2)
return
}
stmt.Close()
fmt.Println(u)
}
调用函数query(1)。
{1 张三 18}
查询多行
// 查询多行
func queryAll(condition int) {
sqlStr := "select id,name,age from user where age>?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("get stmt faild, err:%v\n", err)
return
}
defer stmt.Close()
// 得到查询的结果集rets
rets, err2 := stmt.Query(condition)
if err2 != nil {
fmt.Printf("query faild, err:%v\n", err2)
return
}
var users []user
var u user
// 遍历结果集
for rets.Next() {
err3 := rets.Scan(&u.id, &u.name, &u.age)
if err3 != nil {
fmt.Printf("Scan faild, err:%v\n", err3)
return
}
users = append(users, u)
}
for _, u := range users {
fmt.Println(u)
}
}
调用函数queryAll(18)。
{2 李四 20}
{3 王五 21}
添加
// 添加
func insert(name string, age int) {
sqlStr := "insert into user(name,age) values(?,?)"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare faild, err:%v\n", err)
return
}
defer stmt.Close()
// 执行添加
ret, err2 := stmt.Exec(name, age)
if err2 != nil {
fmt.Printf("stmt exec faild, err:%v\n", err2)
return
}
// 获取受影响行数,使用ret.LastInsertId()可获取新添加的数据的id
i, err3 := ret.RowsAffected()
if err3 != nil {
fmt.Printf("get rowsAffected faild, err:%v\n", err3)
return
}
fmt.Printf("受影响行数:%v\n", i)
}
调用函数insert("柳人高", 24)后可看到数据库中新增了这条数据。
修改
// 修改
func update(u user) {
sqlStr := "update user set name=?,age=? where id=?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare faild, err:%v\n", err)
return
}
defer stmt.Close()
// 执行修改
ret, err2 := stmt.Exec(u.name, u.age, u.id)
if err2 != nil {
fmt.Printf("stmt exec faild, err:%v\n", err2)
return
}
// 获取受影响行数
i, err3 := ret.RowsAffected()
if err3 != nil {
fmt.Printf("get rowsAffected faild, err:%v\n", err3)
return
}
fmt.Printf("受影响行数:%v\n", i)
}
调用函数update(user{ id: 6, name: "仍冰之", age: 25, })可看到id为6的记录被修改。
删除
// 删除
func delete(id int) {
sqlStr := "delete from user where id=?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare faild, err:%v\n", err)
return
}
defer stmt.Close()
// 执行删除
ret, err2 := stmt.Exec(id)
if err2 != nil {
fmt.Printf("stmt exec faild, err:%v\n", err2)
return
}
// 获取受影响行数,使用ret.LastInsertId()可获取新添加的数据的id
i, err3 := ret.RowsAffected()
if err3 != nil {
fmt.Printf("get rowsAffected faild, err:%v\n", err3)
return
}
fmt.Printf("受影响行数:%v\n", i)
}
调用函数delete(1)可将id为1的记录删除。
事务
事务将几个操作绑定为一个原子操作,要么全部成功,要么全部失败。
// 聚合增删改
func iud(tx *sql.Tx, sqlStr string, args ...interface{}) (err error) {
var stmt *sql.Stmt
stmt, err = tx.Prepare(sqlStr)
if err != nil {
return err
}
defer stmt.Close()
// 执行sql语句
_, err = stmt.Exec(args...)
if err != nil {
return err
}
return
}
// 事务
func transaction() (err error) {
// 开启事务
var tx *sql.Tx
tx, err = db.Begin()
if err != nil {
return err
}
// 扣除id为1的员工100元工资
err = iud(tx, "update salary set money=money-100 where id=?", 1)
if err != nil {
// 操作失败,回滚
tx.Rollback()
return err
}
// 奖励id为2的员工100元工资
err = iud(tx, "update salary set money=money+100 where id=?", 2)
if err != nil {
// 操作失败,回滚
tx.Rollback()
return err
}
// 操作成功,提交
tx.Commit()
return
}
执行transaction()函数
end
文章仅做个人学习交流,也许并不完全正确,欢迎指正;