10-gorm-06-更新

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

posted on 2022-02-10 20:51  运维开发玄德公  阅读(47)  评论(0编辑  收藏  举报  来源

导航