gorm增删改查总结

gorm在创建表时使用CreateTable方法进行处理,其参数可以是结构体变量的地址形式,也可以是结构体的地址形式。

例如:

var t Tecent

db.CreateTable(&t)或者db.CreateTable(&Tecent{})。即使类的地址形式中初始化了一些字段,在创建表之后也不会自动添加到表中。如果表已经创建并且表中有数据,再次执行该方法不会再次创建表也不会清除数据。

同理,在创建插入数据时一样可以使用结构体变量地址或者结构体自身的实例化。其实直接使用变量本身也没问题,只不过有些回调函数是使用指针类型调用的,那么就无法调用了。

db.Create(&Tecent{id:1,name:"csdn"})

在插入数据操作时,如果插入数据表的主键为空那么在插入操作后可以使用NewRecord方法判断是否成功,但是如果插入之前就给主键赋值,那该方法就无法判断是否插入成功。因为该方法只是判断主键是否为空。

type Nxin struct {
	Cid int `gorm:"primary_key""`
	Cname string
	Caddress string
}
nn:=Nxin{2,"xiaodai","17ceng"}
fmt.Println(db.NewRecord(nn))
er:=db.Create(&nn)
fmt.Println(db.NewRecord(nn))
if er.Error!=nil{
	panic("primary key is existing")
}
返回的结果都是为false,表示主键不为空。

gorm的文档中提供了一个回调函数BeforeCreate,这个方法可以在插入数据之前调用,如果在这个方法调用之前列已经赋值,那么该方法会覆盖掉原来的值。前提是该方法的调用者是指针类型。


删除操作与其他语言的orm的删除不同,默认的删除方式是软删除,只是修改了字段delete_at字段为当前时间,然后在查询时再也查不到,但是在数据库中依然存在。如果模型继承自gorm.Model,那么Delete方法则软删除,如果不继承那么就是硬删除(清空数据)。

db.Delete(&Nxin{})是删除表中所有的数据。但是是硬删除。Nxin结构体不继承自gorm.Model。
db.Delete(&Dbn{}})软删除。

匹配删除有两种方式:

db.Where("cid=?",8).Delete(&Nxin{})

db.Delete(&Nxin{},"cid=?",9)


修改数据的方式有很多种,以下一一列出比较常见的几种方式:

第一种,先查询在修改最后保存。

var nxi Nxin
db.First(&nxi)
nxi.Caddress="biejing"
db.Save(&nxi)
查询到的数据复制到nxi变量中,然后修改保存。

但是这个方法无法完美的在继承自gorm.Model的结构体中使用。如果对该类型的struct修改,就会导致表中create_at等字段被重置。目前我还没办法解决这个问题,希望有解决办法的读者下面留言告诉我,多谢。

第二种,更新表中所有记录某个字段的值。直接针对某个表的模型进行操作,然后更新。

db.Model(&Nxin{}).Update("caddress","jp")
第三种,匹配更新。也就是对符合条件的数据进行更新。方法比较多,可以参考注释内容。还有其他的方式没有一一列举,不过这些方法已经可以满足平时需要,gorm的文档中提供的其他方法也多数是锦上添花。
	db.Model(&Nxin{}).Where("cid=?",26).Update("caddress","china")//条件写在where里面
	db.Model(&Nxin{}).Where("cid in (?)",[]int{10,11}).Update("caddress","haidian")
	db.Where("cid=?",37).Model(&Nxin{}).Update("caddress","korean")//where与model先后顺序对结果没影响
	db.Where("cid=?",38).Update("caddress","englist").Model(&Nxin{})//但是model不能放在最后

	var nnn Nxin
	nnn=Nxin{Cid:17}//初始化的时候给某些字段赋值,更新时可以直接作为查询匹配条件的记录,然后修改。
	db.Model(&nnn).Update("caddress","franch")
	db.Model(nnn).Update("caddress","german")//此处可以看到地址类型与变量类型对结果没有影响
	db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":"italy"})//同时修改多个字段
	db.Model(&nnn).Update(Nxin{Cname:"nxin",Caddress:"haidian"})
在对表字段更新时可以使用map保存要修改的值,也可以使用结构体类型,但是二者的区别在于如果使用struct更改,那么对某个字段设置成“”,0,false等就不起作用。也就是说:

db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":"italy"})//caddress被设置成italy
db.Model(&nnn).Update(Nxin{Cname:"nxin",Caddress:""})//此处caddress的值并没有被修改成""
db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":""})//caddress被设置成""


查询

第一种,根据gorm自带first,last方法查询。

	var nx Nxin
	nx=Nxin{Cid:19}//查询的条件可以直接写在结构体对象里面
	//db.First(&nx)
	//fmt.Println(nx.Caddress)
	db.First(&nx)
	fmt.Println(nx.Caddress)
可以把查询条件写在struct的变量里,但是因为first,last这些方法只返回一个附个条件的记录。所以可以使用find方法返回多个记录。

	var nx2 []Nxin
	db.Where("cid in (?)",[]int{18,19}).Find(&nx2)
	fmt.Println(nx2)

将返回的值放在nx2数组里。这种办法无法把查询条件写在结构体变量里了,只能写在where里。

 
	var nx3 Nxin
	nx3=Nxin{Cid:20}
	db.Where("caddress=?","dd").Find(&nx3)
	db.Find(&nx3)//select * from nxins where cid=20
	db.Find(&nx3,Nxin{caddress:"jp"})//select * from nxins where cid=20 and caddress="jp"
	db.Find(&nx3,map[string]interface{}{"caddress":"wang",cname:"wang"})
	db.Find(&nx3,"caddress=? and cname=?","bj","wang")
	fmt.Println(nx3)

这种方式为在变量中添加条件,where中再添加一条条件,那么就相当于使用and把两个条件合并。即cid=20 and caddress=dd


	var nx3 Nxin
	nx3=Nxin{Cid:20}
	db.Where("caddress=?","dd").Find(&nx3)
	fmt.Println(nx3)
	var nx4 Nxin
	db.Where(&Nxin{Cid:32,Caddress:"jp"}).First(&nx4)
	fmt.Println(nx4)
	var nx5 []Nxin
	defer db.Close()
	db.Where(map[string]interface{}{"caddress":"jp"}).Find(&nx5)
	fmt.Println(nx5)
在where语句中可以使用map类型或者struct类型进行查询条件添加,但是添加的条件都是and连接。注意:nx5要接受的结果集是很多条数据,但是nx5如果是Nxin类型而不是数组,那么nx5就只会获取最后一条数据。


与where条件类似的还有Not条件语句。如果使用or作为查询条件,那么就要使用or语句了,不过Or语句的用法与where一样,只不过在生成的sql语句中使用的or连接,


	var nx6 []Nxin
	db.Where(map[string]interface{}{"caddress":"jp3"}).Or(map[string]interface{}{"cid":56}).Find(&nx6)
	fmt.Println(nx6)
	var nx7 []Nxin
	db.Or(map[string]interface{}{"cid":56}).Where(map[string]interface{}{"caddress":"jp3"}).Find(&nx7)
	fmt.Println(nx7)
or与where的先后顺序不影响结果的查询。

一些小的查询技巧:

db.Limit(10).where()....//限制只去前10个记录,相当于select * from xxx limit 10

db.Select("name,age").Find(&user)//只查询name,age字段,相当于select name,age from user

db.Select([]string{"name","age"}).Find(&user)

var c int

db.Model(&User{}).Count(&c)//获取表数据行数


对一些复杂业务进行查询时,可以使用join进行连接。

db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
对于已经获取的结果,应该保存在一个结构体的变量中。


如果只是想获得某个表中某个字段的值可以使用Pluck方法。但是返回的结果必须存放在数组中。

var age []int

db.Model(&User{}).Pluck("age",&age)


如果使用model类型进行查询,那么结果会自动填写到类似&user之类的变量中。但是如果使用

db.Table("user")。。。。。。这种类型,结果需要使用scan方法赋值到对应的参数变量中。




好的,下面是gorm增删改查示例: 首先,我们需要定义一个结构体来映射我们的数据表: ```go type User struct { ID uint `gorm:"primary_key"` Name string `gorm:"type:varchar(20);not null"` Age uint8 `gorm:"not null"` Email string `gorm:"type:varchar(100);unique_index"` Password string `gorm:"type:varchar(255);not null"` } ``` 接下来,我们需要创建一个数据库连接并进行初始化: ```go import ( "gorm.io/driver/mysql" "gorm.io/gorm" ) dsn := "user:password@tcp(127.0.0.1:3306)/database_name?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic(err) } // 自动迁移数据表,如果数据表不存在则会自动创建 err = db.AutoMigrate(&User{}) if err != nil { panic(err) } ``` 创建成功后,我们可以进行增删改查操作了: 1. 新增数据 ```go user := &User{ Name: "Tom", Age: 18, Email: "tom@example.com", Password: "123456", } // 创建记录 result := db.Create(user) if result.Error != nil { panic(result.Error) } ``` 2. 查询数据 ```go var users []User // 查找所有记录 result := db.Find(&users) if result.Error != nil { panic(result.Error) } // 根据条件查找记录 result = db.Where("age > ?", 18).Find(&users) if result.Error != nil { panic(result.Error) } ``` 3. 更新数据 ```go // 根据主键更新记录 result := db.Model(&User{}).Where("id = ?", 1).Update("age", 20) if result.Error != nil { panic(result.Error) } ``` 4. 删除数据 ```go // 根据主键删除记录 result := db.Delete(&User{}, 1) if result.Error != nil { panic(result.Error) } ``` 以上就是gorm增删改查示例,希望对你有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值