删除记录

删除一条记录

  1. // 删除一条已有的记录(email 的主键值为 10)
  2. db.Delete(&email)
  3. // DELETE from emails where id=10;
  4. // 通过内联条件删除记录
  5. db.Delete(&Email{}, 20)
  6. // DELETE from emails where id=20;
  7. // 带上其它条件
  8. db.Where("name = ?", "jinzhu").Delete(&email)
  9. // DELETE FROM emails WHERE id=10 AND name = 'jinzhu'

删除钩子

对于删除操作,GORM 支持 BeforeDeleteAfterDelete 钩子,在删除记录时会调用这些方法,详情请参考 钩子

  1. func (u *User) BeforeDelete(tx *gorm.DB) (err error) {
  2. if u.Role == "admin" {
  3. return errors.New("admin user not allowed to delete")
  4. }
  5. return
  6. }

批量删除

如果没有指定带有主键值的记录,GORM 将执行批量删除,删除所有匹配的记录

  1. db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
  2. // DELETE from emails where email LIKE "%jinzhu%";
  3. db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
  4. // DELETE from emails where email LIKE "%jinzhu%";

阻止全局删除

如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回ErrMissingWhereClause错误

您可以使用 1 = 1 之类的条件来强制全局删除

  1. db.Delete(&User{}).Error // gorm.ErrMissingWhereClause
  2. db.Where("1 = 1").Delete(&User{})
  3. // DELETE `users` WHERE 1=1

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!

拥有软删除能力的模型调用 Delete 时,记录不会被数据库。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过普通的查询方法找到该记录。

  1. db.Delete(&user)
  2. // UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
  3. // 批量删除
  4. db.Where("age = ?", 20).Delete(&User{})
  5. // UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
  6. // 在查询时会忽略被软删除的记录
  7. db.Where("age = 20").Find(&user)
  8. // SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

如果您不想引入 gorm.Model,您也可以这样启用软删除特性:

  1. type User struct {
  2. ID int
  3. Deleted gorm.DeletedAt
  4. Name string
  5. }

查找被软删除的记录

您可以使用 Unscoped 找到被软删除的记录

  1. db.Unscoped().Where("age = 20").Find(&users)
  2. // SELECT * FROM users WHERE age = 20;

永久删除

您也可以使用 Unscoped 永久删除匹配的记录

  1. db.Unscoped().Delete(&order)
  2. // DELETE FROM orders WHERE id=10;