go框架(9)-增删改查
增删改查
1. 插入数据
user := User{
Username:"zhangsan",
Password:"123456",
CreateTime:time.Now().Unix(),
}
db.Create(&user)
user.ID // 返回插入数据的主键
result.Error // 返回 error
result.RowsAffected // 返回插入记录的条数
1.1 用指定的字段创建:
db.Select("username","password").Create(&user)
1.2 忽略字段
db.Omit("username").Create(&user)
1.3 批量插入:
var users = []User{{Username: "jinzhu1"}, {Username: "jinzhu2"}, {Username: "jinzhu3"}}
db.Create(&users)
for _, user := range users {
user.ID // 1,2,3
}
使用 CreateInBatches
分批创建时,你可以指定每批的数量,例如:
var users = []User{{Username: "jinzhu_1"}, ...., {Username: "jinzhu_10000"}}
// 数量为 100
db.CreateInBatches(users, 100)
1.4 使用map创建:
db.Model(&User{}).Create(map[string]interface{}{
"Name": "jinzhu", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "jinzhu_1", "Age": 18},
{"Name": "jinzhu_2", "Age": 20},
})
map创建注意,主键不会被填充。
1.5 sql表达式:
DB.Model(&User{}).Create(map[string]interface{}{
"username": "jinzhu",
"password": clause.Expr{SQL: "md5(?)", Vars: []interface{}{"123456"}},
})
1.6 使用原生sql语句:
db.Exec("insert into users (username,password,createtime) values (?,?,?)", user.Username, user.Password, user.CreateTime)
2. 更新数据
在创建一个表
CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id',
`title` varchar(100) NOT NULL COMMENT '商品名',
`price` decimal(10, 2) NULL DEFAULT 0.00 COMMENT '商品价格',
`stock` int(11) DEFAULT '0' COMMENT '商品库存',
`type` int(11) DEFAULT '0' COMMENT '商品类型',
`create_time` datetime NOT NULL COMMENT '商品创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
package dao
import "time"
type Goods struct {
Id int
Title string
Price float64
Stock int
Type int
CreateTime time.Time
}
func (v Goods) TableName() string {
return "goods"
}
func SaveGoods(goods Goods) {
DB.Create(&goods)
}
package dao
import (
"testing"
"time"
)
func TestSaveGoods(t *testing.T) {
goods := Goods{
Title: "毛巾",
Price: 25,
Stock: 100,
Type: 0,
CreateTime: time.Now(),
}
SaveGoods(goods)
}
2.1 保存数据
goods := Goods{}
DB.Where("id = ?", 1).Take(&goods)
goods.Price = 100
//UPDATE `goods` SET `title`='毛巾',`price`=100.000000,`stock`=100,`type`=0,`create_time `='2022-11-25 13:03:48' WHERE `id` = 1
DB.Save(&goods)
2.2 更新单个列
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
DB.Model(&goods).Update("title", "hello")
2.3 更新多列
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
//更新非零值的字段 也可以使用map
DB.Model(&goods).Updates(Goods{
Title: "hello",
Stock: 200,
})
2.4 更新选定的字段
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
DB.Model(&goods).Select("title").Updates(Goods{
Title: "hello",
Stock: 200,
})
排除:
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
DB.Model(&goods).Omit("title").Updates(Goods{
Title: "hello",
Stock: 200,
})
也可以组合使用
Select("*").Omit("title")
gorm更新必须带条件进行更新,否则会返回错误gorm.ErrMissingWhereClause
,或者启用 AllowGlobalUpdate
模式
db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "jinzhu")
2.5 表达式
db.Model(&goods).Update("stock", gorm.Expr("stock + 1"))
db.Model(&goods).Update(map[string]interface{}{"stock": gorm.Expr("stock + 1")})
2.6 子查询更新
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
DB.Model(&goods).Update("title", DB.Model(&User{}).Select("username").Where("id=?", 2))
3. 删除数据
goods := Goods{}
DB.Where("id = ?", 2).Take(&goods)
DB.Delete(&goods)
//根据主键删除
DB.Delete(&Goods{}, 1)
同样的道理,不带条件不能进行删除,必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate
模式
db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
// DELETE FROM users
4. 查询数据
4.1 查询函数
Take:查询一条记录
db.Take(&goods)
First: 根据主键正序排序后,查询第一条数据
db.First(&goods)
Last:根据主键倒序排序后,查询最后一条记录
db.Last(&goods)
Find:查询多条记录
db.Find(&goods)
Pluck:查询一列值
var titles []string db.Model(&Goods{}).Pluck("title", &titles)
当 First、Last、Take 方法找不到记录时,GORM 会返回 ErrRecordNotFound 错误,可以通过对比gorm.ErrRecordNotFound
进行判断,或者使用Find和Limit的组合进行查询。
db.Limit(1).Find(&user)
4.2 where
通过db.Where函数设置条件
函数说明:db.Where(query interface{}, args ...interface{})
参数说明:
比如:
db.Where("id in (?)", []int{1,2,5,6}).Take(&goods)
4.3 select
设置select子句, 指定返回的字段
var goods Goods
DB.Select("id", "title").Find(&goods)
也可以写聚合函数
var total int
DB.Model(&Goods{}).Select("count(*) as total").Pluck("total", &total)
fmt.Println(total)
4.4 order
排序
var goods []Goods
DB.Order("id desc").Find(&goods)
4.5 分页
通过limit和Offset实现
var goods []Goods
DB.Order("create_time desc").Limit(10).Offset(10).Find(&goods)
4.6 count
返回查询匹配的行数
var total int64 = 0
DB.Model(Goods{}).Count(&total)
fmt.Println(total)
4.7 分组
//统计每个商品分类下面有多少个商品
//定一个Result结构体类型,用来保存查询结果
type Result struct {
Type int
Total int
}
var results []Result
//等价于: SELECT type, count(*) as total FROM `goods` GROUP BY type HAVING (total > 0)
db.Model(Goods{}).Select("type, count(*) as total").Group("type").Having("total > 0").Scan(&results)
//scan类似Find都是用于执行查询语句,然后把查询结果赋值给结构体变量,区别在于scan不会从传递进来的结构体变量提取表名.
//这里因为我们重新定义了一个结构体用于保存结果,但是这个结构体并没有绑定goods表,所以这里只能使用scan查询函数。
Group函数必须搭配Select函数一起使用
4.8 直接执行sql语句
sql := "SELECT type, count(*) as total FROM `goods` where create_time > ? GROUP BY type HAVING (total > 0)"
//因为sql语句使用了一个问号(?)作为绑定参数, 所以需要传递一个绑定参数(Raw第二个参数).
//Raw函数支持绑定多个参数
db.Raw(sql, "2022-11-06 00:00:00").Scan(&results)
fmt.Println(results)
go框架(9)-增删改查
http://47.123.5.226:8090//archives/gokuang-jia-9--zeng-shan-gai-cha