Grom操作数据库实践
首先需要下载mysql的驱动
go get gorm.io/driver/mysql
go get gorm.io/gorm
一、简单连接
username := "root" //账号
password := "123456" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "test" //数据库名
timeout := "10s" //连接超时,10秒
// root:root@tcp(127.0.0.1:3306)/gorm?
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
DB, err := gorm.Open(mysql.Open(dsn))
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
// 连接成功
fmt.Println(db)
准备使用的表结构体:
type Student struct {
ID uint `gorm:"size:3"`
Name string `gorm:"size:8"`
Age int `gorm:"size:3"`
Gender bool
Email *string `gorm:"size:32"`
}
二、增加数据
首先使用 DB.AutoMigrate(&Student{})在数据库自动生成对应的表结构
初始表students为空:
1、单条数据插入
email := "xxx@qq.com"
// 创建记录
student := Student{
Name: "khs",
Age: 19,
Gender: true,
Email: &email,
}
db.Create(&student)
有两个地方需要注意
指针类型是为了更好的存null类型,但是传值的时候,也记得传指针- Create接收的是一个
指针,而不是值
由于我们传递的是一个指针,调用完Create之后,student这个对象上面就有该记录的信息了,如创建的id:
DB.Create(&student)
fmt.Printf("%#v\n", student)
main.Student{ID:0x2, Name:"khs", Age:19, Gender:false, Email:(*string)(0x11d40980)}
2、多条数据插入
var studentList []Student
for i := 0; i < 100; i++ {
email := fmt.Sprintf("%d@qq.com", i+1)
studentList = append(studentList, Student{
Name: fmt.Sprintf("机器人%d号", i+1),
Age: 21,
Gender: true,
Email: &email,
})
}
db.Create(&studentList)
三、查询数据
1、查询单条记录
var student Student
DB.Take(&student)
fmt.Println(student)
1.1 根据主键查询
var student Student
DB.Take(&student, 2)
fmt.Println(student)
student = Student{} // 重新赋值
DB.Take(&student, "4")
fmt.Println(student)
Take的第二个参数,默认会根据主键查询,可以是字符串,可以是数字
2.2 根据其他条件查询
var student Student
DB.Take(&student, "name = ?", "机器人27号")
fmt.Println(student)
使用?作为占位符,将查询的内容放入?
同理于mysql语句:
SELECT * FROMstudentsWHERE name = '机器人27号' LIMIT 1
这样可以有效的防止sql注入
他的原理就是将参数全部转义,如
DB.Take(&student, "name = ?", "机器人27号' or 1=1;#")
SELECT * FROM `students` WHERE name = '机器人27号' or 1=1;#' LIMIT 1
1.3 根据struct查询
var student Student
// 只能有一个主要值
student.ID = 2
//student.Name = "枫枫"
DB.Take(&student)
fmt.Println(student)
1.4 获取查询结果
- 获取查询的记录数
count := DB.Find(&studentList).RowsAffected
- 是否查询失败
err := DB.Find(&studentList).Error
查询失败原因有:查询为空,查询条件错误,sql语法错误
- 可以使用判断
var student Student
err := DB.Take(&student, "xx").Error
switch err {
case gorm.ErrRecordNotFound:
fmt.Println("没有找到")
default:
fmt.Println("sql错误")
}
2、查询多条记录
var studentList []Student
DB.Find(&studentList)
for _, student := range studentList {
fmt.Println(student)
}
// 由于email是指针类型,所以看不到实际的内容
// 但是序列化之后,会转换为我们可以看得懂的方式
var studentList []Student
DB.Find(&studentList)
for _, student := range studentList {
data, _ := json.Marshal(student)
fmt.Println(string(data))
}
2.1 根据主键列表查询
var studentList []Student
DB.Find(&studentList, []int{1, 3, 5, 7})
DB.Find(&studentList, 1, 3, 5, 7) // 一样的
fmt.Println(studentList)
2.2 根据其他条件查询
DB.Find(&studentList, "name in ?", []string{"khs", "zhangsan"})
四、修改数据
修改的前提的先查询到记录
1、Save保存所有字段
用于单个记录的全字段更新
它会保存所有字段,即使零值也会保存
var student Student
DB.Take(&student)
student.Age = 23
// 全字段更新
DB.Save(&student)
// UPDATE `students` SET `name`='枫枫',`age`=23,`gender`=true,`email`='xxx@qq.com' WHERE `id` = 1
2 更新指定字段
可以使用select选择要更新的字段
var student Student
DB.Take(&student)
student.Age = 21
// 全字段更新
DB.Select("age").Save(&student)
// UPDATE `students` SET `age`=21 WHERE `id` = 1
3 批量更新
例如我想给年龄21的学生,都更新一下邮箱
var studentList []Student
DB.Find(&studentList, "age = ?", 21).Update("email", "is21@qq.com")
还有一种更简单的方式:
DB.Model(&Student{}).Where("age = ?", 21).Update("email", "is21@qq.com")
// UPDATE `students` SET `email`='is22@qq.com' WHERE age = 21CopyErrorOK!
这样的更新方式也是可以更新零值的
4 更新多列
如果是结构体,它默认不会更新零值
email := "xxx@qq.com"
DB.Model(&Student{}).Where("age = ?", 21).Updates(Student{
Email: &email,
Gender: false, // 这个不会更新
})
// UPDATE `students` SET `email`='xxx@qq.com' WHERE age = 21
如果想让他更新零值,用select就好
email := "xxx1@qq.com"
DB.Model(&Student{}).Where("age = ?", 21).Select("gender", "email").Updates(Student{
Email: &email,
Gender: false,
})
// UPDATE `students` SET `gender`=false,`email`='xxx1@qq.com' WHERE age = 21CopyErrorOK!
五、删除数据
1、根据结构体删除
// student 的 ID 是 `10`
db.Delete(&student)
// DELETE from students where id = 10;
2、删除多个数据
db.Delete(&Student{}, []int{1,2,3})
// 查询到的切片列表
db.Find(&studentList)
db.Delete(&studentList) //全部删除
总结:
在进行Gorm表数据实验的学习过程中,我了解了Gorm连接mysql、表数据的定义、创建、插入、查询等基础操作,也学习了更为复杂的外键约束、联合查询和子查询等操作,对gorm表的数据处理熟练度有了很大提升。
gorm表数据实验让我切实体验到了数据库操作的便捷与高效,学习过程中对于表格数据的概念、结构和操作等方面都有了更深刻的理解和思考,同时也提升了我的技能水平。通过这个过程,我更加热爱学习,也深刻意识到实验对于个人的成长和进步有着举足轻重的作用。
综上所述,通过gorm表数据实验,我不仅掌握了数据库操作的基础知识,还提升了自己的技能水平,更加认识到实验的重要性和深远影响。我相信,在今后的学习生涯中,这种积极的态度与学习方法会帮助我更好地实现个人价值与追求。