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
中制定的参数,修改name
为WuSheng
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