Gorm(四)删除操作
在 Gorm 中,删除操作分为物理删除和软删除,并通过 Unscoped 方法控制是否包含已软删除的记录。以下是详细说明:
一、物理删除(Delete)
物理删除指直接从数据库中删除记录(执行 DELETE 语句),数据无法恢复,适用于确认不需要保留的记录。
基本用法
// 1. 删除单条记录(根据主键)
var user User
db.First(&user, 1) // 查询 ID=1 的用户
db.Delete(&user) // DELETE FROM users WHERE id = 1// 2. 根据条件删除(批量)
db.Where("age < 18").Delete(&User{}) // DELETE FROM users WHERE age < 18// 3. 查看删除结果
result := db.Delete(&user)
fmt.Println("影响行数:", result.RowsAffected) // 1(成功删除1条)
fmt.Println("错误:", result.Error)
特性
- 直接删除:记录从表中永久移除,无法通过常规查询恢复。
- 触发钩子:会执行
BeforeDelete、AfterDelete等钩子函数(如果定义)。 - 无特殊字段依赖:不需要
DeletedAt字段,适用于所有模型。
二、软删除(gorm.DeletedAt)
软删除指不真正删除记录,而是通过标记字段(默认 deleted_at)标识记录已“删除”,查询时默认过滤已标记的记录。适用于需要保留历史数据(如审计、误删恢复)的场景。
实现方式
通过在模型中嵌入 gorm.DeletedAt 字段(gorm.Model 已包含该字段)启用软删除:
type User struct {gorm.Model // 包含 DeletedAt 字段(软删除标记)Name stringAge int
}
gorm.DeletedAt 本质是一个时间类型字段,未删除时为 NULL,删除时被设置为当前时间。
软删除操作
// 1. 软删除单条记录(ID=1)
db.Delete(&User{}, 1) // UPDATE users SET deleted_at = '2024-05-01 12:00:00' WHERE id = 1// 2. 按条件软删除(批量)
db.Where("age > 100").Delete(&User{}) // 标记符合条件的记录为 deleted_at// 结果:记录仍在表中,但 deleted_at 被赋值
特性
- 逻辑删除:记录未被真正删除,仅
deleted_at字段被更新。 - 查询过滤:常规查询(如
Find、First)会自动添加WHERE deleted_at IS NULL,默认不返回软删除记录。 - 触发钩子:会执行
BeforeDelete、AfterDelete钩子(与物理删除共享)。 - 依赖
DeletedAt字段:模型必须包含gorm.DeletedAt才会触发软删除,否则会执行物理删除。
三、Unscoped:查询/操作软删除记录
Unscoped 方法用于取消 Gorm 对软删除记录的过滤,可查询或强制物理删除已软删除的记录。
1. 查询包含软删除的记录
var users []User// 常规查询:不包含软删除记录(默认)
db.Find(&users) // WHERE deleted_at IS NULL// 使用 Unscoped:包含所有记录(包括软删除)
db.Unscoped().Find(&users) // 无 deleted_at 过滤条件
2. 强制物理删除软删除记录
// 对已软删除的记录执行物理删除(ID=1)
db.Unscoped().Delete(&User{}, 1) // DELETE FROM users WHERE id = 1(彻底删除)
3. 恢复软删除记录
通过将 deleted_at 设为 NULL 恢复软删除记录:
// 恢复 ID=1 的软删除记录
db.Unscoped().Model(&User{}).Where("id = ?", 1).Update("deleted_at", nil)
对比与适用场景
| 操作类型 | 本质 | 记录是否保留 | 查询可见性(默认) | 适用场景 |
|---|---|---|---|---|
| 物理删除 | 执行 DELETE 语句 | 不保留 | 不可见 | 确认无需保留的记录 |
| 软删除 | 更新 deleted_at 字段 | 保留 | 不可见 | 需要保留历史、可能恢复的记录 |
注意事项
- 软删除的前提:模型必须包含
gorm.DeletedAt字段(或嵌入gorm.Model),否则Delete方法会执行物理删除。 - 关联删除:软删除主表记录时,关联表的记录不会自动软删除,需手动处理关联逻辑。
- 索引与约束:软删除记录仍占用唯一索引(如
email唯一索引),如需复用唯一值,需先物理删除或恢复后更新。 - 性能影响:软删除会导致表数据量持续增长,需定期归档或清理无用的软删除记录。
总结
- 物理删除(
Delete):彻底删除记录,适用于无保留需求的场景。 - 软删除(依赖
gorm.DeletedAt):逻辑标记删除,保留数据,默认查询不可见。 Unscoped:用于查询软删除记录或强制物理删除已标记的记录。
根据业务对数据保留的需求选择合适的删除方式,软删除更适合需要数据追溯或恢复能力的场景。加粗样式
