CRUD 接口

删除

qianmoQqianmoQ· 更新于 2026-09-23· 阅读 13 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

删除

删除记录删除记录

删除记录时,被删除的值需要包含主键,否则将触发批量删除,例如:

泛型 API泛型 API

ctx := context.Background()


err := gorm.G[Email](db).Where("id = ?", 10).Delete(ctx)



err := gorm.G[Email](db).Where("id = ? AND name = ?", 10, "jinzhu").Delete(ctx)

传统 API传统 API


db.Delete(&email)



db.Where("name = ?", "jinzhu").Delete(&email)

使用主键删除使用主键删除

GORM 允许使用内联条件通过主键删除对象,支持数字类型,详情请参阅查询内联条件

db.Delete(&User{}, 10)


db.Delete(&User{}, "10")


db.Delete(&users, []int{1,2,3})

删除钩子删除钩子

GORM 支持 BeforeDelete、AfterDelete 钩子,这些方法会在删除记录时被调用,详情请参阅钩子

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

批量删除批量删除

指定的值不包含主键时,GORM 将执行批量删除,删除所有匹配的记录

泛型 API泛型 API

ctx := context.Background()


err := gorm.G[Email](db).Where("email LIKE ?", "%jinzhu%").Delete(ctx)

传统 API传统 API

db.Where("email LIKE ?", "%jinzhu%").Delete(&Email{})


db.Delete(&Email{}, "email LIKE ?", "%jinzhu%")

要高效删除大量记录,请将包含主键的切片传递给 Delete 方法。

var users = []User{{ID: 1}, {ID: 2}, {ID: 3}}
db.Delete(&users)


db.Delete(&users, "name LIKE ?", "%jinzhu%")

阻止全局删除阻止全局删除

如果执行不带任何条件的批量删除,GORM 不会执行该操作,并会返回 ErrMissingWhereClause 错误

您必须使用某些条件,或使用原生 SQL,或启用 AllowGlobalUpdate 模式,例如:

泛型 API泛型 API

ctx := context.Background()


err := gorm.G[User](db).Delete(ctx) 


err := gorm.G[User](db).Where("1 = 1").Delete(ctx)

传统 API传统 API

db.Delete(&User{}).Error 

db.Delete(&[]User{{Name: "jinzhu1"}, {Name: "jinzhu2"}}).Error 

db.Where("1 = 1").Delete(&User{})


db.Exec("DELETE FROM users")


db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})

从删除的行返回数据从删除的行返回数据

返回被删除的数据,仅适用于支持 Returning 的数据库,例如:


var users []User
DB.Clauses(clause.Returning{}).Where("role = ?", "admin").Delete(&users)




DB.Clauses(clause.Returning{Columns: []clause.Column{{Name: "name"}, {Name: "salary"}}}).Where("role = ?", "admin").Delete(&users)

软删除软删除

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

调用 Delete 时,记录不会从数据库中移除,而是 GORM 将 DeletedAt 的值设置为当前时间,之后通过普通查询方法无法再找到该数据。


db.Delete(&user)



db.Where("age = ?", 20).Delete(&User{})



db.Where("age = 20").Find(&user)

如果您不想使用 gorm.Model,可以这样启用软删除功能:

type User struct {
  ID      int
  Deleted gorm.DeletedAt
  Name    string
}

查询软删除的记录查询软删除的记录

可以使用 Unscoped 查询软删除的记录

db.Unscoped().Where("age = 20").Find(&users)

永久删除永久删除

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

db.Unscoped().Delete(&order)

删除标志删除标志

默认情况下,gorm.Model 使用 *time.Time 作为 DeletedAt 字段的值,并通过插件 gorm.io/plugin/soft_delete 提供其他数据格式支持

提示 为 DeletedAt 字段创建唯一复合索引时,必须借助插件 gorm.io/plugin/soft_delete 使用其他数据格式,如 unix 秒/标志位,例如:

import "gorm.io/plugin/soft_delete"

type User struct {
ID uint
Name string gorm:"uniqueIndex:udx_name"
DeletedAt soft_delete.DeletedAt gorm:"uniqueIndex:udx_name"
}

Unix 秒Unix 秒

使用 unix 秒作为删除标志

import "gorm.io/plugin/soft_delete"

type User struct {
  ID        uint
  Name      string
  DeletedAt soft_delete.DeletedAt
}


SELECT * FROM users WHERE deleted_at = 0;


UPDATE users SET deleted_at =  WHERE ID = 1;

也可以指定使用 milli(毫秒)或 nano(纳秒)作为值,例如:

type User struct {
  ID    uint
  Name  string
  DeletedAt soft_delete.DeletedAt `gorm:"softDelete:milli"`
  
}


SELECT * FROM users WHERE deleted_at = 0;


UPDATE users SET deleted_at =  WHERE ID = 1;

使用 1 / 0 作为删除标志使用 1 / 0 作为删除标志

import "gorm.io/plugin/soft_delete"

type User struct {
  ID    uint
  Name  string
  IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
}


SELECT * FROM users WHERE is_del = 0;


UPDATE users SET is_del = 1 WHERE ID = 1;

混合模式混合模式

混合模式可以使用 0、1 或 unix 秒来标记数据是否已删除,同时保存删除时间。

type User struct {
  ID        uint
  Name      string
  DeletedAt time.Time
  IsDel     soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` 
  
  
}


SELECT * FROM users WHERE is_del = 0;


UPDATE users SET is_del = 1, deleted_at =  WHERE ID = 1;

GitHub 标签(最新 SemVer)

评论

登录后参与评论

正在加载评论…