gorm-更新

1. save (更新/创建)

主键如果查到,更新数据
主键如果未查到,插入一条数据

    liuBei := xiShu {
        ID: 9,
        Name: "GuanYu",
        Age: 30,
    }
    db.Save(&liuBei)
  • 示例
package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}

func main() {

    db,_ := connect()
    defer db.Close()
    //db.CreateTable(&xiShu{})

    liuBei := xiShu {
        ID: 9,
        Name: "LiuBei",
        Age: 30,
    }
    db.Save(&liuBei)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

2. Update(单列修改)

目前表:

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | GuanYu     |   22 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
|  7 | PangTong   |   25 |
|  8 | HuangZhong |   35 |
+----+------------+------+
9 rows in set (0.01 sec)

2.1 根据主键修改单列

db.Model(&xiShu{ID: 2}).Update("name", "WuSheng")
  • 示例

结构体中我们设置了三个成员,后边演示中可以看到,只有主键的 ID=2生效

func main() {

    db,_ := connect()
    defer db.Close()
    user := xiShu {
        ID: 2,
        Name: "GuanYu",
        Age: 30,
    }
    //var users []xiShu
    result := db.Model(&user).Update("name", "WuSheng")
    fmt.Println(result.Value)
}

说明:
我想说的是,如果结构体定义了很多成员,只有第一个会生效
Name和Age 的值对定位没有影响。
因此,Age:30 依然会查到第二行,然后修改该行。

  • 输出
OK
&{2 WuSheng 30}

可见,result的值是 结构体 user 的值基础上,做了Update() 的修改

  • 数据库的表
mysql> select * from xi_shu where id = 2;
+----+---------+------+
| id | name    | age  |
+----+---------+------+
|  2 | WuSheng |   22 |
+----+---------+------+
1 row in set (0.00 sec)

可见,表的数据中,仅按着Update()修改了name列的值
而age列没因为结构体user的Age值而改变,和输出中result的值不同。

2.2 全部行修改

按上边的结果,我们可以推测,要修改所有行的name值可以:

func main() {

    db,_ := connect()
    defer db.Close()
    result := db.Model(&xiShu{}).Update("name", "WuSheng")
    fmt.Println(result.Value)
}

2.3 使用组合条件更新单个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Update("name", "WuSheng")

2.4 使用 map 更新多个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})

2.5 使用 struct 更新多个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Updates(&xiShu{Name: "WuSheng",Age: 99})

3. Updates

3.1 限制修改字段范围

func main() {
    db,_ := connect()
    defer db.Close()

    db.Model(&xiShu{ID:2}).Select("name").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})
}

表修改结果:

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   22 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

说明:Update()指定了name和age两个字段,但是Select限制了修改范围是name字段,因此age不会改变。

3.2 限制不修改字段

db.Model(&xiShu{ID:2}).Omit("name").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})

表修改结果

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | GuanYu     |   99 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

说明:Update()指定了name和age两个字段,但是Omit限制了修改范围是不能是name字段,因此age不会改变。

4. 不使用钩子

4.1 UpdateColumn/UpdateColumns

上文 2.3.中如果有钩子方法,则会使用钩子,如果不想使用钩子可用UpdateColumn或UpdateColumns。

  • UpdateColumn
db.Model(&xiShu{ID:2}).UpdateColumn("name", "WuSheng")
  • UpdateColumns
db.Model(&user).UpdateColumns(User{Name: "WuSheng", Age: 99})
  • 完整示例

如果使用Update修改,则会调用BeforeUpdate,则 name结果会被修改为BeforeUpdate的参数 HaHa
但使用了UpdateColumn则会执行UpdateColumn中制定的参数,修改nameWuSheng

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}
//钩子
func (LiuBei *xiShu) BeforeUpdate(scope *gorm.Scope) error {
    scope.SetColumn("Name", "HaHa")
    return nil
}


func main() {

    db,_ := connect()
    defer db.Close()
    //不使用钩子
    result := db.Model(&xiShu{ID:2}).UpdateColumn("name", "WuSheng")
    fmt.Println(result.Value)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

4.2 批量修改不使用钩子

db.Table("users").Where("id IN (?)", []int{10, 11}).Update(age: 20)
  • 示例(单行修改使用钩子)
    表原来的数据
mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   10 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

代码

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}

func (LiuBei *xiShu) BeforeUpdate(scope *gorm.Scope) error {
    scope.SetColumn("Age", 10)
    return nil
}


func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Model(&xiShu{ID: 2}).Update("Age",9)
    fmt.Println(result.Value)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

表修改结果

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   10 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

BeforeUpdate参数年龄10,而Update参数年龄 9
结果可见,单行修改使用了BeforeUpdate参数10

  • 示例(多行修改不使用钩子)
    上例中main函数修改如下
func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Table("xi_shu").Where("id IN (?)", []int{1,2,3}).Update("Age",9)
    fmt.Println(result.Value)
}

表修改结果

mysql> mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |    9 |
|  2 | WuSheng    |    9 |
|  3 | ZhangFei   |    9 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

如上可见,1、2、3行都修改为9,使用了Update参数,而不是BeforeUpdate的参数。
注意:即使where中id=1,也是多行修改,只不过是查到了一行而以,因此钩子不生效。

5. RowsAffected(修改影响行数)

func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Table("xi_shu").Where("id IN (?)", []int{1,2,3}).Update("Age",11).RowsAffected
    fmt.Println(result)
}

输出

OK
3

1、2、3 三行被修改,输出为3。

6. Expr(带有表达式的sql更新)

  • 示例

将id=2 的用户 年龄X2+100

func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Model(&xiShu{ID: 2}).Update("age", gorm.Expr("age * ? + ?", 2, 100))
    fmt.Println(result.Value)
}

表结果

mysql> select * from xi_shu where id = 2;
+----+---------+------+
| id | name    | age  |
+----+---------+------+
|  2 | WuSheng |  144 |
+----+---------+------+
1 row in set (0.00 sec)

如上,关羽的年龄从22修改为144

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容