GO语言GORM如何更新字段

字号+ 编辑: Snake 修订: Snake 来源: 原创 2023-09-08 我要说两句(1)

更新

更新所有字段

Save会更新所有字段,即使你没有赋值。

db.First(&user)
user.Name = "qimi"
user.Age = 99
db.Save(&user) // save是更新所有字段
// UPDATE `users` SET `created_at` = '2020-02-16 12:52:20',`updated_at` = '2020-02-16 12:54:23'

更新修改字段

// 更新单个属性,如果它有变化
db.Model(&user).Update("name","hello")
// UPDATE users SET name='hello',updated_at='2013-11-17 21:34:10' WHERE id=111;
 
// 根据给定的条件更新单个属性
db.Model(&user).Where("active = ?",true).Update("name","hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
 
// 使用map更新多个属性,只会更新其中有变化的属性
db.Model(&user).Updates(map[string]interface{}{"name":"hello","age":18,"actives":false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id = 111;
 
// 使用struct 更新多个属性,只会更新其中有变化且非零的字段
db.Model(&user).Updates(User{Name:"hello", Age:18})
// UPDATE users SET name='hello', age=18, updated_at='2013-11-17 21:34:10' WHERE id = 111;
 
//警告:当使用struct更新时,GORM只会更新那些非零的字段
// 对于下面的操作,不会发生任何更新,"",0,false 都是其类型的零值。
db.Model(&user).Updates(User{Name:"",Age:0,Actived:fale})

更新选定字段

如果想更新或忽略某些字段,可以使用Select,Omit

db.Model(&user).Select("name").Updates(map[string]interface{}{"name":""hello,"age":18,"actived":true})
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
 
Db.Model(&user).Omit("name").Updates(map[string]interface{}{"name":"hello","age":18,"actived":false})
// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

无Hooks更新

上面的更新操作会自动运行model的BeforeUpdate,AfterUpdate方法,更新UpateAt时间戳,在更新时保存其Associationd,如果你不想调用这些方法,你可以使用UpdateColumn,UpdateColumns

// 更新单个属性,类似于`Update`
db.Model(&user).UpdateColumn("name","hello")
// UPDATE users SET name='hello' WHERE id=111;

// 更新多个属性,类似于`Updates`
db.Model(&user).UpdateColumns(User{Name:"hello",Age:28})
// UPDATE users SET name='hello', age=28 WHERE id=111;

批量更新

批量更新时Hooks(钩子函数)不会运行。

fb.Table("users").Where("id IN (?)", []int{10,11}).Updates(map[string]interface{}{"name":"hello", "age":18,})
// UPDATE users SET name='hello', age=18 WHERE id IN (10,11);
 
// 使用struct更新时,只会更新非零值字段,若想更新所有字段,请使用map[string]interface{}
db.Model(User{}).Updates(User{Name:"hello",Age:18})
// UPDATE users SET name='hello', age=18;
 
// 使用`RowsAffected`获取更新记录总数
db.Model(User{}).updates(User{Name:"hello", Age:18}).RowsAffected

使用SQL表达式更新(比较有用)

想查询表中的第一条数据保存至USER变量。

var user User
db.First(&user)
 
// 更新一个
db.Model(&user).Update("age",gorm.Expr("age * ? + ?", 2, 100))
// UPDATE `users` SET `age` = age * 2 + 100, `updated_at` = '2020-02-16 13:10:20' WHERE `user`
 
// 更新多个
db.Model(&users).Updates(map[string]interface{}{"age":gorm.Expr("age * ? + ?", 2, 100)})
// UPDATE "users" SET "age" = age * '2' + '100', "updated_at" = '2020-02-16 13:05:51' WHERE `users`
 
// 更新指定的列
db.Model(&user).UpdateColumn("age", gorm.Expr("age - ?",1))
// UPDATE  "users" SET "age" = age - 1 WHERE "id" = '1';
 
// 更新id是1同时年龄大鱼10
db.Model(&user).Where("age > 10").UpdateColumn("age", gorm.Expr("age - ?",1))
// UPDATE "users" SET "age" = age - 1 WHERE "id" = '1' AND quantity >10;
 
例子:让users表中多有的用户的年龄在原来的基础上+2
db.Model(&User{}).Update("age", gorm.Expr("age + ?", 2))

修改Hooks中的值

如果你想修改BeforeUpdate,BeforeSave等Hooks中更新的值,可以使用scope.SetColumn,例如:

一般用在用户名密码加密保存到数据库

func (user *User)BeforeSave(scope *gorm.Scope)(err error) {
if pw, err := bcrypt.GenerateFromPassword(user.Password,0); err == nil {
Scope.SetColumn("EncryptedPassword", pw)
}
}

其他更新选项

// 为update SQL 添加其它的SQL
db.Model(&user).Set("gorm:update_option", "OPTION(OPTIMIZE FOR UNKNOWN)").Update("name","hello")
// UPDATE users SET name=hello, updated_at = 2013-11-17 21:34:10 WHERE id=111 OPTION (OPTIMIZE FOE UNKNOWN) ;
阅完此文,您的感想如何?
  • 有用

    1

  • 没用

    0

  • 开心

    0

  • 愤怒

    0

  • 可怜

    0

1.如文章侵犯了您的版权,请发邮件通知本站,该文章将在24小时内删除;
2.本站标注原创的文章,转发时烦请注明来源;
3.Q群: 2702237 13835667

相关课文
  • gorm如何创建记录与模型定义需要注意什么

  • gorm一般查询与高级查询

  • GORM时间戳跟踪及CURD(增删改查)

  • GORM主键、表名、列名的约定

我要说说
网上嘉宾点评
1 楼 IP 117.174.***.25 的嘉宾 说道 : 很久前
那么BeforeSave中,在不二次查询数据库的情况下是否有办法获取到变动前的值,tx.Statement.Changed()有检查,按说是有途径获取到的