Skip to content
本页目录

CRUD ​

创建 ​

创建记录 ​

go
user := User{Name: "Shibibn", Age: 18, Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数

批量插入 ​

将 slice 传递给 Create 方法

go
var users = []User{{Name: "a1"}, {Name: "a2"}, {Name: "a3"}}
db.Create(&users)

使用 CreateInBatches 分批创建时,你可以指定每批的数量

go
db.CreateInBatches(users, 100)

当插入的数据过多时,就要使用分批创建

为什么要使用分批创建

由于 mysql 对语句有长度限制,当插入的数据很多时,就会导致 sql 语句长度过长而报错。

查询 ​

检索单个对象 ​

First、Take、Last ​

GORM 提供了 First、Take、Last 方法,以便从数据库中检索单个对象。

  • First 主键升序
  • Take 没有指定排序字段
  • Last 主键降序
go
// 获取第一条记录(主键升序)
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;

当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误

go
result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error        // returns error or nil

// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)

根据主键检索 ​

go
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

go
db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";

检索全部对象 ​

go
// Get all records
result := db.Find(&users)
// SELECT * FROM users;

result.RowsAffected // returns found records count, equals `len(users)`
result.Error        // returns error

选择特定字段 ​

go
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;

更新 ​

保存所有字段 ​

Save 会保存所有的字段,即使字段是零值

go
var user User
db.First(&user, 1)
user.Age = 100
db.Save(&user)
//  UPDATE `users` SET `created_at`='2023-03-24 23:58:41.772',`updated_at`='2023-03-26 00:11:49.73',`deleted_at`=NULL,`name`='shibin',`age`=100 WHERE `users`.`deleted_at` IS NULL AND `id` = 1

当保存的数据没有主键时,就会创建一条新数据

go
var user User
user.ID = 0
user.Name = "To"
db.Save(&user)
//  INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`) VALUES ('2023-03-26 00:13:53.304','2023-03-26 00:13:53.304',NULL,'To',0)

更新单个字段 ​

go
// 条件更新
db.Model(&User{}).Where("age=", 100).Update("name", "Go")
//  UPDATE `users` SET `name`='Go',`updated_at`='2023-03-26 00:18:14.385' WHERE `age=` = 100 AND `users`.`deleted_at` IS NULL

// user id 是 1
db.Model(&user).Update("name", "Gin")
// UPDATE `users` SET `name`='Gin',`updated_at`='2023-03-26 00:20:29.598' WHERE `users`.`deleted_at` IS NULL AND `id` = 1

更新多个字段 ​

go
// 根据 struct 更新  只会更新非零值字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

// 根据 map 更新
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

更新选定字段 ​

如果想要在更新时,选定、忽略某些字段,可以使用 Select 、Omit

go
// 根据 map 更新 零值字段也可以更新
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello' WHERE id=111;

db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

// 根据 struct 更新,可以选定更新零值字段
db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
// UPDATE users SET name='new_name', age=0 WHERE id=111;

// 更新所有字段,包括零值字段
db.Model(&user).Select("*").Updates(User{Name: "shibin", Role: "admin", Age: 0})

// 更新除了 Role 的所有字段 包括零值字段
db.Model(&user).Select("*").Omit("Role").Updates(User{Name: "shibin", Role: "admin", Age: 0})

删除 ​

删除一条记录 ​

go
// user  的 id 是 1
db.Delete(&user)
// DELETE from users where id = 1;

// 带额外条件的删除
db.Where("name = ?", "shibin").Delete(&user)
// DELETE from users where id = 1 AND name = "shibin";

注意

删除一条记录时,删除对象需要指定主键,否则会触发批量删除

根据主键删除 ​

go
db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;

db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);

批量删除 ​

如果指定的值不包括主键,那么会执行批量删除,它将删除所有匹配的记录

go
db.Where("email LIKE ?", "%shibin%").Delete(&Email{})
// DELETE from emails where email LIKE "%shibin%";

db.Delete(&Email{}, "email LIKE ?", "%shibin%")
// DELETE from emails where email LIKE "%shibin%"

软删除 ​

如果模型中包含了 gorm.DeletedAt 这个字段,它将会自动使用软删除。软删除时,记录并不会真正删除,但会将 DeletedAt 这个字段的时间设置为删除的时间,并且不能通过正常的查询方法查询到该记录

go
db.Delete(&user)
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 1;

// 批量删除
db.Where("age = ?", 20).Delete(&User{})
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// 查询时会忽略被软删除的记录
db.Where("age = 20").Find(&user)
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

可以使用 Unscoped 查询到被软删除的几率

go
var users []User

db.Unscoped().Find(&users)
// SELECT * FROM `users`

永久删除 ​

go
db.Unscoped().Delete(&user)
// DELETE FROM users WHERE id=1;