Go语言操作数据库

1. 下载依赖

go get -u github.com/go-sql-driver/mysql

2. 测试连接数据库

database/sql包提供了保证SQL或类SQL数据库的泛用接口, 并不提供具体的数据库驱动, 所以使用database/sql包时必须注入(至少)一个数据库驱动

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql" //自动执行init方法 注入数据库驱动
	"log"
)

func main() {
	//数据库信息
	dsn := "root:root@tcp(127.0.0.1:3306)/test"
	//连接数据库
	DB, err := sql.Open("mysql", dsn) //不会校验 用户名,密码是否正确
	if err != nil {
		log.Fatal(err)
		return
	}
	//Ping检查与数据库的连接是否仍有效,如果需要会创建连接
	err = DB.Ping() //校验 dsn 是否正确
	if err != nil {
		log.Fatal(err)
		return
	}
	log.Fatal("测试连接成功")
}

3. 单行查询

package main
import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql" //自动执行init方法 注入数据库驱动
	"log"
)

var db *sql.DB //是一个连接池对象 全局变量
func initDB() (err error) {
	//数据库信息
	dsn := "root:root@tcp(127.0.0.1:3306)/test"
	//连接数据库
	db, err = sql.Open("mysql", dsn) //不会校验 用户名,密码是否正确 这里 db 不能自动初始化(加:)
	if err != nil {
		log.Fatal(err)
		return
	}
	//Ping检查与数据库的连接是否仍有效,如果需要会创建连接
	err = db.Ping() //校验 dsn 是否正确
	if err != nil {
		log.Fatal(err)
		return
	}
	return
}

type user struct {
	id   int
	name string
	age  int
}

func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	var u1 user
	//1.写查询单条记录的sql语句
	sql := `select id,name,age from user where id=2;`
	// 2.执行
	row := db.QueryRow(sql) //从 连接池 拿一个连接出来去数据库查询单条记录
	// 3.拿到结果
	row.Scan(&u1.id, &u1.name, &u1.age) //扫描将匹配行的列复制到dest所指向的值中
	fmt.Printf("%+v", u1)
}

在这里插入图片描述

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql" //自动执行init方法 注入数据库驱动
	"log"
)

type user struct {
	id   int
	name string
	age  int
}

var db *sql.DB //是一个连接池对象 全局变量

func initDB() (err error) {
	//数据库信息
	dsn := "root:root@tcp(127.0.0.1:3306)/test"
	//连接数据库
	db, err = sql.Open("mysql", dsn) //不会校验 用户名,密码是否正确 这里 db 不能自动初始化(加:)
	if err != nil {
		log.Fatal(err)
		return
	}
	//Ping检查与数据库的连接是否仍有效,如果需要会创建连接
	err = db.Ping() //校验 dsn 是否正确
	if err != nil {
		log.Fatal(err)
		return
	}
	return
}

func queryrow(id int) {
	var u1 user
	//1.写查询单条记录的sql语句
	sql := `select id,name,age from user where id=?;`
	// 2.执行
	row := db.QueryRow(sql, id) //从 连接池 拿一个连接出来去数据库查询单条记录
	// 3.拿到结果 必须对row对象调用scan方法,因为该方法会释放数据库链接
	row.Scan(&u1.id, &u1.name, &u1.age) //扫描将匹配行的列复制到dest所指向的值中
	fmt.Printf("%+v", u1)
}

func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	queryrow(1)
}

4. 多行查询

查询id>2的数据

//查询多条语句
func queryMore(n int) {
	//1.sql语句
	sql := `select id,name,age from user where id >?;`
	//2.执行
	rows, err := db.Query(sql, n)
	if err != nil {
		log.Fatal(err)
		return
	}
	//3.一定要关闭rows  rows.scan里 没有 自带关闭
	defer rows.Close()
	//4.循环取值
	for rows.Next() { //有下一个结果就返回 true
		var u1 user
		rows.Scan(&u1.id, &u1.name, &u1.age)
		fmt.Printf("%v\n", u1)
	}
}
func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	//queryrow(2)
	queryMore(2)
}

Go语言操作数据库_第1张图片

5. 插入

插入 更新 删除 都用此操作

// 插入数据
func insertData() {
	//1.写sql语句
	sql := `insert into user(name,age) values('ocean',33)`
	//2.exec
	result, err := db.Exec(sql)
	if err != nil {
		log.Fatal(err)
		return
	}
	//3.如果是 插入数据 的操作,能够拿到插入数据的 id
	id, err := result.LastInsertId()
	if err != nil {
		log.Fatal(err)
		return
	}
	fmt.Println(id)
}
func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	//queryrow(2)
	//queryMore(2)
	insertData()
}

Go语言操作数据库_第2张图片

6. 更新数据

//更新数据
func updateData(newAge, id int) {
	sql := `update user set age=? where id =?`
	result, err := db.Exec(sql, newAge, id)
	if err != nil {
		log.Fatal(err)
		return
	}
	//RowsAffected返回受更新、插入或删除影响的行数。
	affected, err := result.RowsAffected()
	if err != nil {
		log.Fatal(err)
		return

	}
	fmt.Printf("有%d行受影响了", affected)
}
func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	//queryrow(2)
	//queryMore(2)
	//insertData()
	updateData(9999, 1)
}

Go语言操作数据库_第3张图片

7. 删除

//删除
func deleteData(id int) {
	sql := `delete from user where id=?`
	exec, err := db.Exec(sql, id)
	if err != nil {
		log.Fatal(err)
	}
	affected, err := exec.RowsAffected()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("有%d行受影响", affected)
}

8. 预处理

1. 普通sql语句执行过程

1.客户端对sql语句进行占位符替换得到完整的sql语句。
2.客户端发送完整sql语句到mysql服务端。
3.mysql服务端执行完整的sql语句并将结果返回给客户端。

2. 预处理执行过程

1.将sql语句分为两部分,命令与数据。
2.先把命令部分发送给MySQL服务端,MySQL服务端进行sql预处理。
3.然后把数据部分发送给MySQL服务端,MySQL服务端对sql语句进行占位符替换。
4.mysql服务端执行完整的sql语句并将结果返回给客户端。

3.为什么要进行预处理

1.避免sql注入问题。
2.提升服务器性能,节省后续编译的成本。 优化重复执行的SQL语句

4.预处理插入数据

prepare方法会先将sql语句发送给MySQL服务端,返回一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令

//预处理插入
func prepareInsert() {
	sql := `insert into user(name,age) values(?,?)` //命令一致,只用改变数字
	prepare, err := db.Prepare(sql)                 //传递预处理命令
	if err != nil {
		log.Fatal(err)
		return
	}
	//需关闭
	defer prepare.Close()
	//后续需要拿prepare去执行操作
	var m = map[string]int{
		"PG":   20,
		"AFJN": 22,
		"HX":   23,
	}
	for key, value := range m {
		exec, err := prepare.Exec(key, value)
		if err != nil {
			log.Fatal(err)
		}
		affected, err := exec.RowsAffected()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("有%d行受影响", affected)
	}
}

9. MySQL事务操作

func transaction() {
	//1.开启事务
	begin, err := db.Begin()
	if err != nil {
		log.Fatal("开启失败", err)
	}
	//2.执行多个sql语句
	sql1 := `update user set age=age-5 where id =2`
	sql2 := `update user set age=age+5 where id =7`
	//3.执行sql1
	_, err = begin.Exec(sql1)
	if err != nil {
		//出错 回滚
		begin.Rollback()
		fmt.Println("执行语句1失败出错回滚!")
		return
	}
	//4.执行语句2
	_, err = begin.Exec(sql2)
	if err != nil {
		//出错回滚
		begin.Rollback()
		fmt.Println("执行语句2失败出错回滚!")
		return
	}
	//5.上面两步都执行成功,就提交本次事务
	err = begin.Commit()
	if err != nil {
		//提交出错,回滚
		begin.Rollback()
		fmt.Println("事务提交出错了")
		return
	}
	fmt.Println("事务执行成功了")
}

10. sqlx使用 增,删,改,基本与sql一致

简化操作 提高开发效率
使用sqlx时 结构体定义变量 首字母必须大写

查询单条语句

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql" //自动执行init方法 注入数据库驱动
	"github.com/jmoiron/sqlx"
	"log"
)

type user struct {
	Id   int
	Name string
	Age  int
}

//改变地方
var db *sqlx.DB //是一个连接池对象 全局变量

func initDB() (err error) {
	//数据库信息
	dsn := "root:root@tcp(127.0.0.1:3306)/test"
	//连接数据库 改变地方
	//连接到数据库并使用ping进行验证
	db, err = sqlx.Connect("mysql", dsn) //不会校验 用户名,密码是否正确 这里 db 不能自动初始化(加:)
	if err != nil {
		log.Fatal(err)
		return
	}
	return
}

func main() {
	err := initDB()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("测试数据库连接成功!")
	sql := `select id,name,age from user where id =8`
	var u user
	err = db.Get(&u, sql)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u)
}

查询多条语句

	var users []user
	sql2 := `select * from user`
	db.Select(&users, sql2)
	if err != nil {
		log.Fatal(err)
		return
	}
	fmt.Printf("%+v", users)

在这里插入图片描述

11.

12.

你可能感兴趣的:(GOLang,数据库,mysql,java)