gorm基础-3.单表查询

先使用gorm对单张表进行增删改查

表结构

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"`
}

添加记录

email := "xxx@qq.com"
// 创建记录
student := Student{
  Name:   "枫枫",
  Age:    21,
  Gender: true,
  Email:  &email,
}
DB.Create(&student)

有两个地方需要注意

  1. 指针类型是为了更好的存null类型,但是传值的时候,也记得传指针
  2. Create接收的是一个指针,而不是值

由于我们传递的是一个指针,调用完Create之后,student这个对象上面就有该记录的信息了,如创建的id

DB.Create(&student)
fmt.Printf("%#v\n", student)  
// main.Student{ID:0x2, Name:"zhangsan", Age:23, Gender:false, Email:(*string)(0x11d40980)}

批量插入

Create方法还可以用于插入多条记录

var studentList []Student
for i := 0; i < 100; i++ {
  studentList = append(studentList, Student{
    Name:   fmt.Sprintf("机器人%d号", i+1),
    Age:    21,
    Gender: true,
    Email:  &email,
  })
}
DB.Create(&studentList)

查询单条记录

var student Student
DB.Take(&student)
fmt.Println(student)

获取单条记录的方法很多,我们对比sql就很直观了

DB = DB.Session(&gorm.Session{Logger: Log})
var student Student
DB.Take(&student)  
// SELECT * FROM `students` LIMIT 1
DB.First(&student) 
// SELECT * FROM `students` ORDER BY `students`.`id` LIMIT 1
DB.Last(&student)  
// SELECT * FROM `students` ORDER BY `students`.`id` DESC LIMIT 1

根据主键查询

var student Student
DB.Take(&student, 2)
fmt.Println(student)

student = Student{} // 重新赋值
DB.Take(&student, "4")
fmt.Println(student)

Take的第二个参数,默认会根据主键查询,可以是字符串,可以是数字

根据其他条件查询

var student Student
DB.Take(&student, "name = ?", "机器人27号")
fmt.Println(student)

使用?作为占位符,将查询的内容放入?

SELECT * FROM `students` WHERE name = '机器人27号' LIMIT 1

这样可以有效的防止sql注入

他的原理就是将参数全部转义,如

DB.Take(&student, "name = ?", "机器人27号' or 1=1;#")

SELECT * FROM `students` WHERE name = '机器人27号\' or 1=1;#' LIMIT 1

根据struct查询

var student Student
// 只能有一个主要值
student.ID = 2
//student.Name = "枫枫"
DB.Take(&student)
fmt.Println(student)

获取查询结果

获取查询的记录数

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错误")
}

查询多条记录

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))
}

根据主键列表查询

var studentList []Student
DB.Find(&studentList, []int{1, 3, 5, 7})
DB.Find(&studentList, 1, 3, 5, 7)  // 一样的
fmt.Println(studentList)

根据其他条件查询

DB.Find(&studentList, "name in ?", []string{"枫枫", "zhangsan"})

更新

更新的前提的先查询到记录

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

零值也会更新

var student Student
DB.Take(&student)
student.Age = 0
// 全字段更新
DB.Save(&student)
// UPDATE `students` SET `name`='枫枫',`age`=0,`gender`=true,`email`='xxx@qq.com' WHERE `id` = 1

更新指定字段

可以使用select选择要更新的字段

var student Student
DB.Take(&student)
student.Age = 21
// 全字段更新
DB.Select("age").Save(&student)
// UPDATE `students` SET `age`=21 WHERE `id` = 1

批量更新

例如我想给年龄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 = 21

这样的更新方式也是可以更新零值的

更新多列

如果是结构体,它默认不会更新零值

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 = 21

如果不想多写几行代码,则推荐使用map

DB.Model(&Student{}).Where("age = ?", 21).Updates(map[string]any{
  "email":  &email,
  "gender": false,
})

更新选定字段

Select选定字段

Omit忽略字段

删除

根据结构体删除

// student 的 ID 是 `10`
db.Delete(&student)
// DELETE from students where id = 10;

删除多个

db.Delete(&Student{}, []int{1,2,3})

// 查询到的切片列表
db.Delete(&studentList)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值