Golang中的Mysql操作

文章目录

go语言中 database/sql包提供了保证SQL或类SQL数据库的泛用接口,常用的数据库驱动有 github.com/go-sql-driver/mysql

初始化连接

以下代码定义了一个全局变量 db,它将用于保存数据库连接的实例。然后定义了initDB 函数负责初始化数据库连接。它使用给定的连接字符串创建一个数据库连接实例,然后通过 Ping 方法检查是否能够成功连接到数据库。在这里,CheckError 函数用于检查和处理每个步骤可能发生的错误。

go 复制代码
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func CheckError(err error, arg string) {
	if err != nil {
		fmt.Printf("%s err:%v", arg, err)
	}
}

func initDB() (err error) {
	dsn := "root:123456@tcp(127.0.0.1:3306)/users"
	db, err = sql.Open("mysql", dsn)
	CheckError(err, "Open")
	err = db.Ping()
	CheckError(err, "ping")
	return nil
}

func main() {
	err := initDB()
	CheckError(err, "init db")
	defer db.Close()
}

查询数据

先定义一个struct来存储查询的数据

go 复制代码
type userData struct {
	id       int
	age      int
	name     string
}

单行查询

在 Go 语言中,db.QueryRow() 用于执行一次查询并期望返回最多一行结果。如果没有找到结果,它不会返回 nil,而是返回一个实现了 Row 接口的非空值。

在调用 QueryRow() 后,通常会使用 Scan() 方法从结果中提取数据。Scan() 方法负责将结果的列映射到相应的变量,并在需要时触发底层查询的执行。在调用 Scan() 之前,QueryRow() 不会执行实际的查询。

go 复制代码
// 单行查询db.QueryRow()执行一次查询,并期望返回最多一行结果(即Row)
func queryRowDemo() {
	sqlStr := "select id,name,age from user where id=?"
	var u userData
	// 非常重要:确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
	err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age)
	CheckError(err, "scan")
	fmt.Printf("id:%d,name:%s,username:%s", u.id, u.name, u.age)
}

多行查询

多行查询db.Query()执行一次查询,返回多行结果(即Rows),一般用于执行select命令。

go 复制代码
func queryMultiRowDemo() {
	sqlStr := "select id,name,age from user where id>?"
	rows, err := db.Query(sqlStr, 0)
	CheckError(err, "query")
	defer rows.Close()

	// 循环读取结果集中的数据
	for rows.Next() {
		var u userData
		err := rows.Scan(&u.id, &u.name, &u.age)
		CheckError(err, "rows scan")
		fmt.Printf("id:%d,name:%s,age:%d\n", u.id, u.name, u.age)
	}
}

以上代码使用 rows.Next() 遍历结果集中的每一行,然后使用 rows.Scan 将当前行的数据扫描到相应的变量中。

插入数据

插入、更新和删除操作都使用Exec方法。

go 复制代码
func InsertRowDemo() {
	sqlStr := "insert into user(name,age) values (?,?)"
	ret, err := db.Exec(sqlStr, "王五", 18)
	CheckError(err, "insert")
	theID, err := ret.LastInsertId()
	CheckError(err, "LastInsertId")
	fmt.Println("insert success,the id is", theID)
}

使用 ret.LastInsertId() 获取最后插入的 ID,通常在表中有一个自增的主键时使用。

更新数据

这里将 user 表中 id 为 5 的行的 age 列更新为 100。并使用 ret.RowsAffected() 获取受影响的行数,即更新操作实际影响的行数。

go 复制代码
func UpdateRowDemo() {
	sqlStr := "update user set age=? where id=?"
	ret, err := db.Exec(sqlStr, 100, 5)
	CheckError(err, "update")
	n, err := ret.RowsAffected() // 操作影响的行数
	CheckError(err, "RowsAffected")
	fmt.Printf("update success, affected rows:%d\n", n)
}

删除数据

go 复制代码
func DeleteRowDemo() {
	sqlStr := "delete from user where id=?"
	ret, err := db.Exec(sqlStr, 5)
	CheckError(err, "delete")
	n, err := ret.RowsAffected()
	CheckError(err, "RowsAffected")
	fmt.Printf("delete success,affected rows:%d\n", n)
}

预编译

预编译执行过程:

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

Golang中通过database/sql使用下面的Prepare方法来实现预处理操作。

go 复制代码
func (db *DB) Prepare(query string) (*Stmt, error)

查询数据

go 复制代码
func PrepareQueryDemo() {
	Sqlstr := "select id,name,age from user where id > ?"
	stmt, err := db.Prepare(Sqlstr)
	CheckError(err, "Prepare stmt")
	defer stmt.Close()
	rows, err := stmt.Query(0)
	CheckError(err, "Query")
	defer rows.Close()
	for rows.Next() {
		var u userData
		err := rows.Scan(&u.id, &u.name, &u.age)
		CheckError(err, "rows scan")
		fmt.Printf("id:%d,name:%s,age:%d\n", u.id, u.name, u.age)
	}
}

插入数据

go 复制代码
func InsertQueryDemo() {
	Sqlstr := "insert into user(name,age) values(?,?)"
	stmt, err := db.Prepare(Sqlstr)
	CheckError(err, "stmt")
	defer stmt.Close()
	_, err = stmt.Exec("wangdong", 20)
	CheckError(err, "insert")
	fmt.Println("insert success")
}

更新和删除操作类似插入操作。

相关推荐
清风fu杨柳20 分钟前
centos7 arm版本编译qt5.6.3详细说明
开发语言·arm开发·qt
醉颜凉22 分钟前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
_小柏_25 分钟前
C/C++基础知识复习(20)
开发语言
程序员小明z34 分钟前
基于Java的药店管理系统
java·开发语言·spring boot·毕业设计·毕设
我是哈哈hh1 小时前
HTML5和CSS3的进阶_HTML5和CSS3的新增特性
开发语言·前端·css·html·css3·html5·web
曾经的三心草1 小时前
Mysql之约束与事件
android·数据库·mysql·事件·约束
宋发元2 小时前
如何使用正则表达式验证域名
python·mysql·正则表达式
Dontla2 小时前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
张某布响丸辣2 小时前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
路遇晚风2 小时前
力扣=Mysql-3322- 英超积分榜排名 III(中等)
mysql·算法·leetcode·职场和发展