删除数据看似简单,但涉及软删除、级联删除等概念,需要仔细理解。
根据主键删除:
db.Delete(&User{}, 1)
删除模型实例:
user := User{ID: 1}
db.Delete(&user)
删除多条记录:
db.Delete(&User{}, []int{1, 2, 3})
根据条件删除:
db.Where("age < ?", 18).Delete(&User{})
db.Where("name LIKE ?", "%测试%").Delete(&User{})
删除所有记录:
db.Where("1 = 1").Delete(&User{})
这很危险,生产环境要谨慎。
如果模型有 gorm.DeletedAt 字段,删除操作是软删除:
type User struct {
ID uint
Name string
DeletedAt gorm.DeletedAt
}
db.Delete(&User{}, 1)
这不会真正删除记录,而是设置 deleted_at 字段。
要真正删除,用 Unscoped:
db.Unscoped().Delete(&User{}, 1)
模型嵌入 gorm.DeletedAt 后自动启用软删除:
type User struct {
gorm.Model
Name string
}
gorm.Model 包含 ID、CreatedAt、UpdatedAt、DeletedAt。
软删除的记录不会出现在普通查询中:
db.Find(&users)
要查询包括软删除的记录:
db.Unscoped().Find(&users)
只查询软删除的记录:
db.Unscoped().Where("deleted_at IS NOT NULL").Find(&users)
删除符合条件的所有记录:
db.Where("status = ?", "inactive").Delete(&User{})
获取删除数量:
result := db.Where("age < ?", 18).Delete(&User{})
fmt.Println(result.RowsAffected)
某些数据库支持返回删除的数据:
var users []User
db.Clauses(clause.Returning{}).Where("age < ?", 18).Delete(&users)
MySQL 不支持,PostgreSQL 和 SQL Server 支持。
关联记录的删除行为由外键约束决定。在模型中定义:
type User struct {
ID uint
Name string
Orders []Order
}
type Order struct {
ID uint
UserID uint
User User
}
删除用户时,订单的处理取决于数据库外键设置:
CASCADE - 同时删除订单SET NULL - 订单的 user_id 设为 NULLRESTRICT - 有订单时禁止删除用户GORM 的关联标签可以指定:
type User struct {
ID uint
Orders []Order `gorm:"constraint:OnDelete:CASCADE;"`
}
删除操作会触发钩子:
func (u *User) BeforeDelete(tx *gorm.DB) error {
if u.Role == "admin" {
return errors.New("不能删除管理员")
}
return nil
}
func (u *User) AfterDelete(tx *gorm.DB) error {
log.Printf("用户 %s 已删除", u.Name)
return nil
}
Unscoped().Delete() 也会触发钩子。
物理删除
真正从数据库移除记录:
软删除
标记记录为已删除:
选择建议:
恢复被软删除的记录:
db.Unscoped().Model(&User{}).Where("id = ?", 1).Update("deleted_at", nil)
外键约束
ERROR: update or delete on table "users" violates foreign key constraint
有关联记录时无法删除。解决方案:
记录不存在
删除不存在的记录不会报错,RowsAffected 为 0:
result := db.Delete(&User{}, 999)
fmt.Println(result.RowsAffected)
忘记条件
db.Delete(&User{})
这会删除所有记录(软删除)。生产环境务必加条件。
删除操作要区分软删除和物理删除。软删除适合业务数据,物理删除适合敏感数据。无论哪种,都要注意条件限制,避免误删。