GORM批量更新删除

Gorm 操作指导

在使用 gorm 时,存在一些坑,这些坑如果不注意就极易影响到整个数据库的数据,故以此文作为记录来作为使用的指导。

Create record

gorm 新建数据的方法有 Create()方法,但不能实现部分插入。它采用整体插入,struct 中声明变量都会转化为 sql 语句中的字段插入,对于未给赋值的变量采用对应类型的零值来插入。

具体例子如下:

// 声明 Users 结构
type Users struct {
    ID uint
    Email string
    Passwords string `gorm:"column:password"`
    IsFemale int // 数据库中默认值为 1
    IsActived int // 数据库中默认值为 1
}
user1 := {
  ID: 6,
  Email: "123",
}
user2 := {
  Email: "test",
  Passwords: "123",
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

当使用 Create() 方法来插入数据时

db.Create(&user2)
// generate sql is 
// UPDATE `users` SET `email` = '123', `password` = '', `is_female` = '0', `is_actived` = '0'  WHERE `users`.`id` = 6
  • 1
  • 2
  • 3

而我们想要的 sql 为:

INSERT INTO `users` (`email`,`password`) VALUES ('test','123')
  • 1

Issue:如何实现部分插入? 或避免使用 gorm 插入时,struct 中的零值覆盖默认值呢?

Answer:gorm 文档中并没有提供部分插入的实现,我们只能采取全部插入的方式,但可以使用以下方式来避免零值覆盖默认值。

方式一

// 此方法不需要显示的调用,会在程序调用 Create() 方法前自动调用
func (user *User) BeforeCreate() error {
  scope.SetColumn("IsFemale", 1)
  scope.SetColumn("IsActived", 1)
  return nil
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

方式二

// Omit() 中填入所有此次插入需要忽略的值,Users struct 中的其他值使用给定值或对应零值来更新
db.Omit("IsFemale", "IsActived").Create(&user)
  • 1
  • 2

Update Record

gorm 中的 Save() 方法也不是部分更新,会更新 struct 中全部的字段,未赋值的字段使用零值来更新,所以一般不建议直接使用 Save() 来更新,因为极易覆盖数据库中原有的值。

// Save will include all fields when perform the Updating SQL, even it is not changed
user1.IsFemale = 0
db.Save(&user)
// generate sql is 
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 
  • 1
  • 2
  • 3
  • 4
  • 5

更新一条记录中的多个值

  1. 使用 Struct 结构来更新(db.Model(&user).Updates(Users{...}) )

正确用法

db.Model(&user1).Updates(Users{IsFemale: 1, Email: "test"})
// generated sql is 
// update users set is_female = 1, email = 'test' where id = 6
  • 1
  • 2
  • 3

错误用法Model(...) 方法中的实例没有包含主键,导致更新了所有记录(而且并不是按实例中所给的条件更新)。

db.Model(&user2).Updates(Users{IsFemale: 1, Email: "test"})
// or wanted sql: update users set is_female = 1, email = 'test' where email = '123'
// but generate sql is
// update users set is_female = 1, email = 'test'
  • 1
  • 2
  • 3
  • 4

Note:struct 类型并不能更新对应变量类型的零值

db.Model(&user1).Updates(Users{IsFemale: 0, Email: "test"})
// generate sql is 
// update users set email = 'test' where id = 6
  • 1
  • 2
  • 3
  1. 使用 Map 结构来更新(db.Model(&user).Updates(map[string]interface{}{...})

正确用法

db.Model(&user1).Updates(map[string]interface{}{"IsFemale": 0, "Email": "test"})
// generate sql is
// update users set is_female = 0, email = 'test' where id = 6
  • 1
  • 2
  • 3

错误用法Model(...) 方法中的实例没有包含主键,导致更新了所有记录(而且并不是按实例中所给的条件更新)。

db.Model(&user2).Updates(Users{IsFemale: 1, Email: "test"})
// or wanted sql: update users set is_female = 1, email = 'test' where email = '123'
// but generate sql is
// update users set is_female = 1, email = 'test'
  • 1
  • 2
  • 3
  • 4

更新多条记录

用法

db.Model(&Users{}).Where(&Users{Passwords:"123"}).UpdateColumns(Users{IsFemale: 1})
// generate sql is 
// update users set is_female = 1 where password = '123'
// note:struct 对零值的更新不起作用
  • 1
  • 2
  • 3
  • 4

更多 where 字句的用法详见 query

Delete Record

单条删除

使用 Delete() 方法进行单条删除时,在删除前必须确保传入主键必须存在否则会 删除整张表

db.Delete(&user1)
// gegerate sql is : delete from users where id = 6
db.Delete(&user2)
// generate sql is : delete from users
  • 1
  • 2
  • 3
  • 4

批量删除

db.Where(Users{Email: "test"}).Delete(Users{})
// generate sql is 
// delete from users where email = 'test'
  • 1
  • 2
  • 3

更多 where 字句的用法详见 query

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值