检索单个对象
GORM提供了First,Take,Last方法,以便从数据库中检索单个对象。当查询数据库时它添加了LIMIT 1 条件,且没有找到记录时,它会返回ErrRecordNotFound错误
// 获取第一条记录(主键升序)
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)
First和Last会根据主键排序,分别查询第一条和最后一条记录。只有在目标struct是指针或者通过db.Model()指定model时,该方法才有效。此外,如果相关model没有定义主键,那么将按model的第一个字段进行排序。例如:
var user User
var users []User
// 有效,因为目标 struct 是指针
db.First(&user)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1
// 有效,因为通过 `db.Model()` 指定了 model
result := map[string]interface{}{}
db.Model(&User{}).First(&result)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1
// 无效
result := map[string]interface{}{}
db.Table("users").First(&result)
// 配合 Take 有效
result := map[string]interface{}{}
db.Table("users").Take(&result)
// 未指定主键,会根据第一个字段排序(即:`Code`)
type Language struct {
Code string
Name string
}
db.First(&Language{})
// SELECT * FROM `languages` ORDER BY `languages`.`code` LIMIT 1
用主键搜索
如果主键是数字类型,你可以使用内联条件来检索对象。传入字符串参数时,需要特别注意SQL的注入问题
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;
db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);
如果主键是字符串(例如像 uuid)查询将被写成这样:
db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";
检索全部对象
// 获取全部记录
result := db.Find(&users)
// SELECT * FROM users;
result.RowsAffected // 返回找到的记录数,相当于 `len(users)`
result.Error // returns error
条件
String条件
// 获取第一条匹配的记录
db.Where("name = ?", "张三").First(&user)
// SELECT * FROM users WHERE name = '张三' ORDER BY id LIMIT 1;
// 获取全部匹配的记录
db.Where("name <> ?", "张三").Find(&users)
// SELECT * FROM users WHERE name <> '张三';
// IN
db.Where("name IN ?", []string{"张三", "张三 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('张三','张三 2');
// LIKE
db.Where("name LIKE ?", "%zs%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%zs%';
// AND
db.Where("name = ? AND age >= ?", "张三", "22").Find(&users)
// SELECT * FROM users WHERE name = '张三' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
// SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Struct&Map条件
// Struct
db.Where(&User{Name: "张三", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "张三" AND age = 20 ORDER BY id LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "张三", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "张三" AND age = 20;
// 主键切片条件
db.Where([]int64{20, 21, 22}).Find(&users)
// SELECT * FROM users WHERE id IN (20, 21, 22);
注意:当使用结构作为条件查询时,GORM只会查询非零值字段。这意味着如果您的字段值为0,’’,false或其他零值,该字段不会被用于构建查询条件,例如:
db.Where(&User{Name: "张三", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "张三";
如果想要包含零值查询条件,你可以使用map,其会包含所有key-value的查询条件,例如:
db.Where(map[string]interface{}{"Name": "张三", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "张三" AND age = 0;
指定结构体查询字段
当使用struct进行查询时,你可以通过向Where()传入struct来指定查询条件的字段,值,表名,例如:
db.Where(&User{Name: "张三"}, "name", "Age").Find(&users)
// SELECT * FROM users WHERE name = "张三" AND age = 0;
db.Where(&User{Name: "张三"}, "Age").Find(&users)
// SELECT * FROM users WHERE age = 0;
内联条件
查询条件也可以被内联到First和Find之类的方法中,其用法类似于Where
// 根据主键获取记录,如果是非整型主键
db.First(&user, "id = ?", "string_primary_key")
// SELECT * FROM users WHERE id = 'string_primary_key';
// Plain SQL
db.Find(&user, "name = ?", "张三")
// SELECT * FROM users WHERE name = "张三";
db.Find(&users, "name <> ? AND age > ?", "张三", 20)
// SELECT * FROM users WHERE name <> "张三" AND age > 20;
// Struct
db.Find(&users, User{Age: 20})
// SELECT * FROM users WHERE age = 20;
// Map
db.Find(&users, map[string]interface{}{"age": 20})
// SELECT * FROM users WHERE age = 20;
Not条件
构建NOT条件,用法与 Where 类似
db.Not("name = ?", "张三").First(&user)
// SELECT * FROM users WHERE NOT name = "张三" ORDER BY id LIMIT 1;
// Not In
db.Not(map[string]interface{}{"name": []string{"张三", "张三 2"}}).Find(&users)
// SELECT * FROM users WHERE name NOT IN ("张三", "张三 2");
// Struct
db.Not(User{Name: "张三", Age: 18}).First(&user)
// SELECT * FROM users WHERE name <> "张三" AND age <> 18 ORDER BY id LIMIT 1;
// 不在主键切片中的记录
db.Not([]int64{1,2,3}).First(&user)
// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;
Or条件
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
// Struct
db.Where("name = '张三'").Or(User{Name: "张三 2", Age: 18}).Find(&users)
// SELECT * FROM users WHERE name = '张三' OR (name = '张三 2' AND age = 18);
// Map
db.Where("name = '张三'").Or(map[string]interface{}{"name": "张三 2", "age": 18}).Find(&users)
// SELECT * FROM users WHERE name = '张三' OR (name = '张三 2' AND age = 18);
选择特定字段
Select允许你指定从数据库中检索哪些字段,默认情况下,GORM会检索所有字段
db.Select("name", "age").Find(&users)
// SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
// SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
// SELECT COALESCE(age,'42') FROM users;
Order
指定从数据库检索记录时的排序方式
db.Order("age desc, name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;
// 多个 order
db.Order("age desc").Order("name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;
db.Clauses(clause.OrderBy{
Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},
}).Find(&User{})
// SELECT * FROM users ORDER BY FIELD(id,1,2,3)
Limit&Offset
Limit指定获取记录的最大数量Offset指定在开始返回记录之前要跳过的记录数量
db.Limit(3).Find(&users)
// SELECT * FROM users LIMIT 3;
// 通过 -1 消除 Limit 条件
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
// SELECT * FROM users LIMIT 10; (users1)
// SELECT * FROM users; (users2)
db.Offset(3).Find(&users)
// SELECT * FROM users OFFSET 3;
db.Limit(10).Offset(5).Find(&users)
// SELECT * FROM users OFFSET 5 LIMIT 10;
// 通过 -1 消除 Offset 条件
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
// SELECT * FROM users OFFSET 10; (users1)
// SELECT * FROM users; (users2)
作者:admin 创建时间:2024-10-23 07:47
最后编辑:admin 更新时间:2024-10-23 07:48
最后编辑:admin 更新时间:2024-10-23 07:48