增
u := User{
Username:"codebaoku",
Password:"123456",
CreateTime:time.Now().Unix(),
}
db.Create(&u)
// 等价于 SQL 语句:INSERT INTO `users` (`username`,`password`,`createtime`) VALUES ('codebaoku','123456','1540824823')
u.ID // 返回主键 ID,默认主键名为 ID,也可以通过 gorm 标签定义
u.Error // 返回 error
u.RowsAffected // 返回插入记录的条数
查
Scan取结果要传入指针的地址并在试用期前进行非空校验
Raw&Row&Rows&Scan
原生sql:
有结果要取用raw, 反之用Exec
sql = ""
args = make([]string, 0)
var res string
//单个结果使用Raw执行sql后用Scan取出结果
r1 := db.Raw(sql, args)
row.Scan(&res)
//单个结果使用Raw执行sql后使用Row再用Scan取出结果
r1 := db.Raw(sql, args)
row := r1.Row()
row.Scan(&res)
//单个结果使用Raw执行sql后使用Rows后须调用Next方法再用Scan取出结果
r1 := db.Raw(sql, args)
rows, err := r1.Rows()
rows.Next()
rows.Scan(&res)
//多个结果使用Raw执行sql后使用Rows后须,循环调用Next方法用Scan取出结果
r1 := db.Raw(sql, args)
rows, err := r1.Rows()
for rows.Next(){
rows.Scan(&res)
}
gorm:
//单个结果使用row
row := db.Select("ziduan").Table("aaa").Where("conditation").Row()
row.Scan(&res)
//单个结果直接scan
db.Select("ziduan").Table("aaa").Where("condition").Scan(&res)
//多个结果使用gorm架构直接赋值给数组
res := make([]string, 0)
db.Select("ziduan").Table("aaa").Where("conditation").Find(&res)
//多个结果使用Raw执行sql后使用Rows后须,循环调用Next方法用Scan取出结果
rows, err := db.Select("ziduan").Table("aaa").Rows()
for rows.Next(){
rows.Scan(&res)
}
First&Last&Take&Find&Pluck
food := Food{} //用于存放结果的结构体
var foods []Food
// 查询一条记录,根据主键ID排序(正序),返回第一条记录。
// 等价于:SELECT * FROM `foods` ORDER BY `foods`.`id` ASC LIMIT 1
db.First(&food)
// 查询一条记录, 根据主键ID排序(倒序),返回第一条记录。
// 等价于:SELECT * FROM `foods` ORDER BY `foods`.`id` DESC LIMIT 1
db.Last(&food)
// 等价于:SELECT * FROM `foods` LIMIT 1
db.Take(&food)
// 查询多条记录,Find函数返回的是一个数组。
db.Find(&foods)
// 查询一列值。
var val []string
db.Model(&Food{}).Pluck("title", &titles)
// Pluck提取了title字段,保存到titles变量
// Model函数是为了绑定一个模型实例,可以从里面提取表名。
改
======================================================================================
// Save
// 先查询一条记录, 保存在模型变量food
food := Food{}
db.Where("id = ?", 2).Take(&food)
// 等价于: SELECT * FROM `foods` WHERE (id = '2') LIMIT 1
// 修改food模型的值
food.Price = 100
// 将传入结构体的主键作为条件进行筛选后更新所有字段
db.Save(&food)
// 等价于: UPDATE `foods` SET `title` = '可乐', `type` = '0',
// `price` = '100', `stock` = '26', `create_time` = '2018-11-06 11:12:04'
// WHERE `foods`.`id` = '2'
===============================================
// Update
// 通过 food 模型的主键 id 的值作为 where 条件,更新 price 字段值。
db.Model(&food).Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25'
// WHERE `foods`.`id` = '2'
// 注意这里的 Model 参数
// 使用的是 Food{},新生成一个空白的模型变量
// 没有绑定任何记录。
// 因为 Food{} 的 id 为空,gorm库就不会以 id 作为条件
// where 语句就是空的
db.Model(&Food{}).Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25'
// 根据自定义条件更新记录,而不是根据主键 id
db.Model(&Food{}).Where("create_time > ?", "2018-11-06 20:00:00").
Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25'
// WHERE (create_time > '2018-11-06 20:00:00')
===============================================
// Updates
// 通过结构体变量设置更新字段
updataFood := Food{
Price:100,
Title:"aa",
}
// 根据 food 模型更新数据库记录
// Updates 会忽略掉 updataFood 结构体变量的零值字段
// 所以生成的 sql 语句只有 price 和 title 字段。
db.Model(&food).Updates(&updataFood)
// 等价于: UPDATE `foods` SET `price` = '100',
// `title` = 'aa' WHERE `foods`.`id` = '2'
// 可传入空的Food结构体,使用Where语句筛选需要更新的记录
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Updates 会忽略掉结构体变量的零值字段
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 使用 map 类型更新传入的包括零值的所有字段值
// 定义 map 类型,key 为字符串,value 为 interface{} 类型
// 方便保存任意值
data := make(map[string]interface{})
data["stock"] = 0 //零值字段
data["price"] = 35
db.Model(&Food{}).Where("id = ?", 2).Updates(data)
// 等价于: UPDATE `foods` SET `price` = '35', `stock` = '0' WHERE (id = '2')
======================================================================================
// 使用gorm.Expr函数进行表达式形式的更新
db.Model(&food).Update("stock", gorm.Expr("stock + 1"))
// 等价于: UPDATE `foods` SET `stock` = stock + 1 WHERE `foods`.`id` = '2'
删
// 删除模型数据一般用于删除之前查询出来的模型变量绑定的记录。
food := Food{}
// 先查询一条记录, 保存在模型变量 food
db.Where("id = ?", 2).Take(&food)
// 等价于: SELECT * FROM `foods` WHERE (id = '2') LIMIT 1
// 删除 food 对应的记录,通过主键 Id 标识记录
db.Delete(&food)
// 等价于: DELETE from `foods` where id=2;
==========================================================================
// 根据 Where 条件删除数据
//db.Where(条件表达式).Delete(空模型变量指针)
// 必须传空结构体指针到Delete中指定表名
db.Where("type = ?", 5).Delete(&Food{})
// 等价于:DELETE from `foods` where (`type` = 5);
Group
(Group函数必须搭配Select函数一起使用)
// 统计每个商品分类下面有多少个商品
// 定一个Result结构体类型,用来保存查询结果
type Result struct {
Type int
Total int
}
var results []Result
// 等价于:
// SELECT type, count(*) as total FROM `foods`
// GROUP BY type HAVING (total > 0)
db.Model(Food{}).Select("type, count(*) as total").
Group("type").Having("total > 0").Scan(&results)
// scan类似Find都是用于执行查询语句,然后把查询结果赋值给结构体变量
// 区别在于scan不会从传递进来的结构体变量提取表名.
// 这里因为我们重新定义了一个结构体用于保存结果
// 但是这个结构体并没有绑定foods表,所以这里只能使用scan查询函数。
事务
// ==============================================================
// 自动事务处理
db.Transaction(func(tx *gorm.DB) error{
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
// 返回任何错误都会回滚事务
return err
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
return err
}
// 返回 nil 提交事务
return nil
})
// ==============================================================
// 手动事务处理
tx := db.Begin() //开启事务
// 操作1
if err := tx.Create(&food).Error; err != nil {
tx.Rollback() // 失败则调用该函数进行回滚
return
}
// 操作2
if err := tx.Delete(&food).Error; err != nil {
tx.Rollback() // 失败则调用该函数进行回滚
return
}
tx.Commit() //执行事务
Tips
结构体定义映射的表名和字段名
type test struct{
TestId string `gorm:"column:id" json:"nativename"`
Nnn string `gorm:"column:n"`
Mmm string `gorm:"column:m"`
}
func (t test) TableName() string{
retrun "tb_test"
}
空值NULL相关的判断和更新
// 判断
db.Select("id").Where("flag is null")
// 更新
sql := "update tb_name set flag = NULL WHERE id = ?"
db.Exec(sql, 2)
db.Table("tb_test").
Where("id = ?",1).
Updates(map[string]interface{}{"m":1, "n":nil})
//golang的nil映射为数据库的NULL
联查&模糊匹配&页码查询&取值
sql := "a.id = ?"
serchId = "xxxxxx"
serchKeyword = "aaa"
ss := "%"+serchKeyword+"%"
var c *int64
db := db.Debug().Select("a.id, b.name, c.xxx").
Table("tb1 a").
Joins("left join tb2 b").
Joins("left join tb3 c").Where(sql, serchId).
Where("a.ppp like ? or b.ppp like ?", ss, ss).
Order("a.id desc"). //降序排列
Offset( ( page - 1 ) * pagesize).Limit(pagesize)
db.Count(&c)
rows, err := db.Rows()
for rows.Next(){
rows.Scan(...)
}
本文详细介绍了GORM库在Go语言中进行数据库CRUD操作,包括创建、读取、更新和删除,以及高级查询技巧如SQL原生和GORM方法的对比,关联查询,模糊搜索,分页查询,以及如何处理空值和事务管理。
2321





