教程 > gorm 教程 > 阅读:163

gorm 删除——迹忆客-ag捕鱼王app官网

删除一条记录

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

// email 的 id 是 `10`
db.delete(&email)
// delete from emails where id = 10;
// 带额外条件的删除
db.where("name = ?", "jinzhu").delete(&email)
// delete from emails where id = 10 and name = "jinzhu";

根据主键删除

gorm 允许通过主键(可以是复合主键)和内联条件来删除对象,它可以使用数字(如以下例子。也可以使用字符串——译者注)。查看 查询-内联条件(query inline conditions) 了解详情。

db.delete(&user{}, 10)
// delete from users where id = 10;
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);

delete hook

对于删除操作,gorm 支持 beforedelete、afterdelete hook,在删除记录时会调用这些方法,查看 hook 获取详情

func (u *user) beforedelete(tx *gorm.db) (err error) {
    if u.role == "admin" {
        return errors.new("admin user not allowed to delete")
    }
    return
}

批量删除

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

db.where("email like ?", "%jinzhu%").delete(&email{})
// delete from emails where email like "%jinzhu%";
db.delete(&email{}, "email like ?", "%jinzhu%")
// delete from emails where email like "%jinzhu%";

阻止全局删除

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

对此,你必须加一些条件,或者使用原生 sql,或者启用 allowglobalupdate 模式,例如:

db.delete(&user{}).error // gorm.errmissingwhereclause
db.where("1 = 1").delete(&user{})
// delete from `users` where 1=1
db.exec("delete from users")
// delete from users
db.session(&gorm.session{allowglobalupdate: true}).delete(&user{})
// delete from users

返回删除行的数据

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

// 返回所有列
var users []user
db.clauses(clause.returning{}).where("role = ?", "admin").delete(&users)
// delete from `users` where role = "admin" returning *
// users => []user{{id: 1, name: "jinzhu", role: "admin", salary: 100}, {id: 2, name: "jinzhu.2", role: "admin", salary: 1000}}
// 返回指定的列
db.clauses(clause.returning{columns: []clause.column{{name: "name"}, {name: "salary"}}}).where("role = ?", "admin").delete(&users)
// delete from `users` where role = "admin" returning `name`, `salary`
// users => []user{{id: 0, name: "jinzhu", role: "", salary: 100}, {id: 0, name: "jinzhu.2", role: "", salary: 1000}}

软删除

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

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

// user 的 id 是 `111`
db.delete(&user)
// update users set deleted_at="2013-10-29 10:23" where id = 111;
// 批量删除
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;

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

type user struct {
  id      int
  deleted gorm.deletedat
  name    string
}

查找被软删除的记录

我们可以使用 unscoped 找到被软删除的记录

db.unscoped().where("age = 20").find(&users)
// select * from users where age = 20;

永久删除

我们也可以使用 unscoped 永久删除匹配的记录

db.unscoped().delete(&order)
// delete from orders where id=10;

delete flag

默认情况下,gorm.model 使用 *time.time 作为 deletedat 字段的值。此外,通过 gorm.io/plugin/soft_delete 插件还支持其它数据格式。

提示 当使用 deletedat 字段创建唯一复合索引时,你必须通过 gorm.io/plugin/soft_delete 等插件将字段定义为时间戳之类的数据格式,例如:

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 秒级时间戳作为 delete flag

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"`
  // deletedat soft_delete.deletedat `gorm:"softdelete:nano"`
}
// 查询
select * from users where deleted_at = 0;
// 删除
update users set deleted_at = /* 当前毫秒、纳秒时间戳 */ where id = 1;

使用 1 / 0 作为 delete flag

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"` // 使用 `1` `0` 标识
  // isdel     soft_delete.deletedat `gorm:"softdelete:,deletedatfield:deletedat"` // 使用 `unix second` 标识
  // isdel     soft_delete.deletedat `gorm:"softdelete:nano,deletedatfield:deletedat"` // 使用 `unix nano second` 标识
}
// 查询
select * from users where is_del = 0;
// 删除
update users set is_del = 1, deleted_at = /* current unix second */ where id = 1;

查看笔记

扫码一下
查看教程更方便
网站地图