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{})

参数说明:

参数名

说明

query

sql语句的where子句, where子句中使用问号(?)代替参数值,则表示通过args参数绑定参数

args

where子句绑定的参数,可以绑定多个参数

比如:

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
作者
pony
发布于
2024年05月09日
许可协议