检索单个对象
GORM 提供了 First、Take、Last 方法,以便从数据库中检索单个对象。
//用户表结构体
type User struct {
gorm.Model
Email string `gorm:"unique"` //unique表唯一
Password string
Role int
}
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;
// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;
// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error // returns error or nil
// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)
tips:对单个对象使用Find而不带limit,db.Find(&user)将会查询整个表并且只返回第一个对象,这是性能不高并且不确定的。
主键查询
当目标对象有一个主键值时,将使用主键构建查询条件
var user = User{ID: 10}
db.First(&user)
// SELECT * FROM users WHERE id = 10;
var result User
db.Model(User{ID: 10}).First(&result)
// SELECT * FROM users WHERE id = 10;
条件查询
If the object’s primary key has been set, then condition query wouldn’t cover the value of primary key but use it as a ‘and’ condition. For example: 如果设置了对象的主键,则条件查询不会覆盖主键的值,而是将其作为“与”条件。例如:
var user = User{ID: 10}
db.Where("id = ?", 20).First(&user)
// SELECT * FROM users WHERE id = 10 and id = 20 ORDER BY id ASC LIMIT 1
下面是条件查询常用语句
var student []Student
DB.Where("",).Find(&student)
//查询匹配的第一条
DB.Where("name = ?", "手作机1").First(&student)
//查询所有匹配记录
DB.Where("Age = ?", 21).Find(&student)
//查询匹配项之外记录
DB.Where("Name <> ?", "量产机1号").Find(&student)
//查询多条指定内容
DB.Where("Name IN ?", []string{"量产机1号", "量产机2号"}).Find(&student)
//查询关键字
DB.Where("Name LIKE ?", "%手作机%").Find(&student)
多条件查询AND
DB.Where("Age > ? AND Name != ?", 20, "小琴").Find(&student)
按时间查询Time
today := time.Now()
lastWeek := time.Date(
2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
DB.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&student)
strust map条件查询
//Struct结构体查询
// DB.Where(&Student{Name: "量产机1号"}).Find(&student)
//map查询
// DB.Where(map[string]interface{}{"Age": 21}).Find(&student)
// Slice of primary keys使用切片查询主键
DB.Where([]int64{3313, 3315, 3312}).Find(&student)
注意当使用结构体查询时,GORM 只会查询非零字段,这意味着如果你的字段值为 0 、 '' 、 false 或其他零值,它将不会用于构建查询条件 要在查询条件中包含零值,您可以使用map,它将包含所有键值作为查询条件
DB.Where(map[string]interface{}{"Gender": false}).Find(&student)
查询后排序
//查询后排序 desc降序 asc升序
DB.Order("Age asc").Find(&student, "Name LIKE ?", "%量产机%")
//循环打印出来
for _, s := range student {
fmt.Println(s.ID, s.Name, s.Age, *s.Email)
}
Limit & Offset的运用:分页查询
//分页查询 Limit & Offset
// 假设page是当前页数,从1开始
page := 1
// 每页的数量
pageSize := 2
// 计算偏移量
offset := (page - 1) * pageSize
// 使用Limit和Offset方法进行分页查询
//Limit表示每页限制查询 Offset计算的是偏移量,一般是offset := (page - 1) * pageSize
DB.Order("Age").Limit(pageSize).Offset(offset).Find(&student, "Name LIKE ?", "%量产机%")
fmt.Println(student)
查询后按照属性分组
查询性别后,通过性别分组并且列出具体名称
type Res struct {
Gender int
Count int64
NameList string `gorm:"column:nameList"`
}
var res []Res
DB.Model(Student{}).Select("gender", "Count(*) as Count", "group_concat(Name) as nameList").Group("Gender").Scan(&res)
fmt.Println(res)
查询以某个名字为开头的用户,并计算他们的年龄总和
// type Res struct {
// Name string
// Count int64
// }
// var res []Res
// DB.Model(Student{}).Select("Name,sum(Age) as Count").Where("Name LIKE ?", "量产机%").Group("Name").Find(&res)
// fmt.Println(res)
// var total int64
// DB.Model(Student{}).Where("Name LIKE ?", "量产机%").Select("sum(Age)").Scan(&total)
// fmt.Println(total)
高级查询
结构体查询,只获取指定字段内容
// type APIUser struct {
// ID uint
// Name string
// Gender int
// }
// var api []APIUser
// DB.Model(&Student{}).Limit(4).Find(&api)
// fmt.Println(api)
嵌套式查询
嵌套查询可以减少对数据库的操作,在不需要获取到中间值的时候可以采用
DB.Where("Age = (?)", DB.Table("f_Student").Select("AVG(Age)")).Find(&student)
//实际上操作等同于
var avgAge float64
DB.Table("f_Student").Select("AVG(Age)").Scan(&avgAge)
DB.Where("Age = (?)", DB.Table("f_Student").Select("AVG(Age)")).Find(&student)