查询是数据库操作的重头戏。GORM 提供了链式 API,让查询既灵活又易读。
First 获取第一条记录,按主键排序:
var user User
db.First(&user)
等价于 SELECT * FROM users ORDER BY id LIMIT 1。
Take 获取一条记录,不排序:
db.Take(&user)
Last 获取最后一条记录,按主键倒序:
db.Last(&user)
这三个方法如果找不到记录,会返回 ErrRecordNotFound 错误:
err := db.First(&user, 999).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
fmt.Println("记录不存在")
}
直接传主键值:
db.First(&user, 1)
db.First(&user, "1")
多个主键查询:
var users []User
db.Find(&users, []int{1, 2, 3})
Find 获取所有匹配记录:
var users []User
db.Find(&users)
找不到记录不会报错,只是返回空切片。
Where 添加查询条件:
db.Where("name = ?", "张三").First(&user)
db.Where("age > ?", 20).Find(&users)
多个条件:
db.Where("name = ? AND age > ?", "张三", 20).Find(&users)
使用结构体或 map 作为条件:
db.Where(&User{Name: "张三", Age: 20}).First(&user)
db.Where(map[string]interface{}{"name": "张三", "age": 20}).Find(&users)
结构体查询会忽略零值,map 不会。
只查询需要的字段:
db.Select("name", "age").Find(&users)
db.Select("name, age").Find(&users)
用函数计算:
db.Select("*, upper(name) as name").Find(&users)
Order 指定排序:
db.Order("age desc").Find(&users)
db.Order("age desc, name asc").Find(&users)
Limit 限制返回条数:
db.Limit(10).Find(&users)
Offset 跳过指定条数:
db.Offset(10).Find(&users)
组合实现分页:
page := 2
pageSize := 10
db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&users)
去重:
db.Distinct("name").Find(&users)
Group 分组查询:
type Result struct {
Age int
Count int
}
var results []Result
db.Model(&User{}).Select("age, count(*) as count").Group("age").Find(&results)
Having 过滤分组:
db.Model(&User{}).Select("age, count(*) as count").Group("age").Having("count > ?", 1).Find(&results)
var count int64
db.Model(&User{}).Count(&count)
var sum int
db.Model(&User{}).Select("sum(age)").Scan(&sum)
var avg float64
db.Model(&User{}).Select("avg(age)").Scan(&avg)
查询结果映射到自定义结构:
type UserDTO struct {
Name string
Age int
}
var users []UserDTO
db.Model(&User{}).Select("name, age").Scan(&users)
也可以映射到 map:
var results []map[string]interface{}
db.Table("users").Find(&results)
只查询单列:
var names []string
db.Model(&User{}).Pluck("name", &names)
var ages []int
db.Model(&User{}).Pluck("age", &ages)
查询记录,不存在则初始化(不保存):
var user User
db.Where(User{Name: "张三"}).FirstOrInit(&user)
可以指定初始化属性:
db.Where(User{Name: "张三"}).FirstOrInit(&user, User{Age: 20})
查询记录,不存在则创建:
var user User
db.Where(User{Name: "张三"}).FirstOrCreate(&user)
创建时附加属性:
db.Where(User{Name: "张三"}).FirstOrCreate(&user, User{Age: 20})
在 Where 中使用子查询:
db.Where("age > (?)", db.Model(&User{}).Select("avg(age)")).Find(&users)
在 From 中使用:
db.Table("(?) as u", db.Model(&User{}).Select("name, age")).Find(&results)
直接执行 SQL:
var users []User
db.Raw("SELECT * FROM users WHERE age > ?", 20).Scan(&users)
Exec 执行不返回数据的 SQL:
db.Exec("UPDATE users SET age = age + 1 WHERE name = ?", "张三")
查询后检查错误:
err := db.Where("name = ?", "张三").First(&user).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// 记录不存在
} else {
// 其他错误
}
}
GORM 的查询 API 丰富,链式调用让代码清晰。掌握条件、排序、分页、聚合这些基本操作,能应对大部分场景。、