Struct/Structs/Scan
这三个方法用于便捷地将查询的结果转换为struct/*struct
或者[]struct/[]*struct
数据。
1、Struct
: 将查询结果转换为一个struct
对象,查询结果应当是特定的一条记录,并且pointer
参数应当为struct
对象的指针地址(*struct
或者**struct
),使用方式例如:
Code Block |
---|
|
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.Table("user").Where("id", 1).Struct(user) |
或者
Code Block |
---|
|
user := &User{}
err := db.Table("user").Where("id", 1).Struct(user) |
前两种方式都是预先初始化对象(提前分配内存),推荐的方式:
Code Block |
---|
|
user := (*User)(nil)
err := db.Table("user").Where("id", 1).Struct(&user) |
这种方式只有在查询到数据的时候才会执行初始化及内存分配。注意在用法上的区别,特别是传递参数类型的差别(前两种方式传递的参数类型是*User
,这里传递的参数类型其实是**User
)。
2、Structs
: 将多条查询结果集转换为一个[]struct/[]*struct
数组,查询结果应当是多条记录组成的结果集,并且pointer
应当为数组的指针地址,使用方式例如:
Code Block |
---|
|
users := ([]User)(nil)
// 或者 var users []User
err := db.Table("user").Structs(&users) |
或者
Code Block |
---|
|
users := ([]*User)(nil)
// 或者 var user []*User
err := db.Table("user").Structs(&users) |
3、Scan
: 该方法会根据输入参数pointer
的类型选择调用Struct
还是Structs
方法。如果结果是特定的一条记录,那么调用Struct
方法;如果结果是slice
类型则调用Structs
方法。
LeftJoin/RightJoin/InnerJoin
LeftJoin
左关联查询;RightJoin
右关联查询;InnerJoin
内关联查询;
Info |
---|
其实我们并不推荐使用Join 进行联表查询,特别是在数据量比较大、并发请求量比较高的场景中,容易产生性能问题,也容易提高维护的复杂度。建议您在确定有此必要的场景下使用。此外,您也可以参考 模型关联-ScanList 章节,数据库只负责存储数据和简单的单表操作,通过ORM 提供的功能实现数据聚合。 |
使用示例:
// 查询符合条件的单条记录(第一条)
// SELECT u.*,ud.site FROM user u LEFT JOIN user_detail ud ON u.uid=ud.uid WHERE u.uid=1 LIMIT 1
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.site").Where("u.uid", 1).One()
// 查询指定字段值
// SELECT ud.site FROM user u RIGHT JOIN user_detail ud ON u.uid=ud.uid WHERE u.uid=1 LIMIT 1
r, err := db.Table("user u").RightJoin("user_detail ud", "u.uid=ud.uid").Fields("ud.site").Where("u.uid", 1).Value()
// 分组及排序
// SELECT u.*,ud.city FROM user u INNER JOIN user_detail ud ON u.uid=ud.uid GROUP BY city ORDER BY register_time asc
r, err := db.Table("user u").InnerJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.city").Group("city").Order("register_time asc").All()
// 不使用join的联表查询
// SELECT u.*,ud.city FROM user u,user_detail ud WHERE u.uid=ud.uid
r, err := db.Table("user u,user_detail ud").Where("u.uid=ud.uid").Fields("u.*,ud.city").All()
Group/Order
分组与排序
Group
方法用于查询分组,Order
方法用于查询排序。使用示例:
// SELECT COUNT(*) total,age FROM `user` GROUP BY age
r, err := db.Table("user").Fields("COUNT(*) total,age").Group("age").All()
// SELECT * FROM `student` ORDER BY class asc,course asc,score desc
r, err := db.Table("student").Order("class asc,course asc,score desc").All()
同时,goframe
的ORM
提供了一些常用的排序方法:
Code Block |
---|
|
// 按照指定字段递增排序
func (m *Model) OrderAsc(column string) *Model
// 按照指定字段递减排序
func (m *Model) OrderDesc(column string) *Model
// 随机排序
func (m *Model) OrderRandom() *Model |
使用示例:
Code Block |
---|
|
// SELECT `id`,`title` FROM `article` ORDER BY `created_at` ASC
db.Model("article").Fields("id,title").OrderAsc("created_at").All()
// SELECT `id`,`title` FROM `article` ORDER BY `views` DESC
db.Model("article").Fields("id,title").OrderDesc("views").All()
// SELECT `id`,`title` FROM `article` ORDER BY RAND()
db.Model("article").Fields("id,title").OrderRandom().All() |
Having
条件过滤
Having
方法用于查询结果的条件过滤。使用示例:
// SELECT COUNT(*) total,age FROM `user` GROUP BY age HAVING total>100
r, err := db.Table("user").Fields("COUNT(*) total,age").Group("age").Having("total>100").All()
// SELECT * FROM `student` ORDER BY class HAVING score>60
r, err := db.Table("student").Order("class").Having("score>?", 60).All()
自定义数据表别名
// SELECT * FROM `user` AS u LEFT JOIN `user_detail` as ud ON(ud.id=u.id) WHERE u.id=1 LIMIT 1
r, err := db.Table("user", "u").LeftJoin("user_detail", "ud", "ud.id=u.id").Where("u.id", 1).One()
r, err := db.Table("user").As("u").LeftJoin("user_detail", "ud", "ud.id=u.id").Where("u.id", 1).One()
常见数据查询示例
1. 基本操作
Where + string
,条件参数使用字符串和预处理。
// 查询多条记录并使用Limit分页
// SELECT * FROM user WHERE uid>1 LIMIT 0,10
r, err := db.Table("user").Where("uid > ?", 1).Limit(0, 10).All()
// 使用Fields方法查询指定字段
// 未使用Fields方法指定查询字段时,默认查询为*
// SELECT uid,name FROM user WHERE uid>1 LIMIT 0,10
r, err := db.Table("user").Fileds("uid,name").Where("uid > ?", 1).Limit(0, 10).All()
// 支持多种Where条件参数类型
// SELECT * FROM user WHERE uid=1 LIMIT 1
r, err := db.Table("user").Where("u.uid=1",).One()
r, err := db.Table("user").Where("u.uid", 1).One()
r, err := db.Table("user").Where("u.uid=?", 1).One()
// SELECT * FROM user WHERE (uid=1) AND (name='john') LIMIT 1
r, err := db.Table("user").Where("uid", 1).Where("name", "john").One()
r, err := db.Table("user").Where("uid=?", 1).And("name=?", "john").One()
// SELECT * FROM user WHERE (uid=1) OR (name='john') LIMIT 1
r, err := db.Table("user").Where("uid=?", 1).Or("name=?", "john").One()
Where + slice
,预处理参数可直接通过slice
参数给定。
// SELECT * FROM user WHERE age>18 AND name like '%john%'
r, err := db.Table("user").Where("age>? AND name like ?", g.Slice{18, "%john%"}).All()
// SELECT * FROM user WHERE status=1
r, err := db.Table("user").Where("status=?", g.Slice{1}).All()
Where + map
,条件参数使用任意map
类型传递。
// SELECT * FROM user WHERE uid=1 AND name='john' LIMIT 1
r, err := db.Table("user").Where(g.Map{"uid" : 1, "name" : "john"}).One()
// SELECT * FROM user WHERE uid=1 AND age>18 LIMIT 1
r, err := db.Table("user").Where(g.Map{"uid" : 1, "age>" : 18}).One()
Where + struct/*struct
,struct
标签支持 orm/json
,映射属性到字段名称关系。
type User struct {
Id int `json:"uid"`
UserName string `orm:"name"`
}
// SELECT * FROM user WHERE uid =1 AND name='john' LIMIT 1
r, err := db.Table("user").Where(User{ Id : 1, UserName : "john"}).One()
// SELECT * FROM user WHERE uid =1 LIMIT 1
r, err := db.Table("user").Where(&User{ Id : 1}).One()
以上的查询条件相对比较简单,我们来看一个比较复杂的查询示例。
Code Block |
---|
|
condition := g.Map{
"title like ?" : "%九寨%",
"online" : 1,
"hits between ? and ?" : g.Slice{1, 10},
"exp > 0" : nil,
"category" : g.Slice{100, 200},
}
// SELECT * FROM article WHERE title like '%九寨%' AND online=1 AND hits between 1 and 10 AND exp > 0 AND category IN(100,200)
r, err := db.Table("article").Where(condition).All() |
2. in
查询
使用字符串、slice
参数类型。当使用slice
参数类型时,预处理占位符只需要一个?
即可。
// SELECT * FROM user WHERE uid IN(100,10000,90000)
r, err := db.Table("user").Where("uid IN(?,?,?)", 100, 10000, 90000).All()
r, err := db.Table("user").Where("uid", g.Slice{100, 10000, 90000}).All()
// SELECT * FROM user WHERE gender=1 AND uid IN(100,10000,90000)
r, err := db.Table("user").Where("gender=? AND uid IN(?)", 1, g.Slice{100, 10000, 90000}).All()
// SELECT COUNT(*) FROM user WHERE age in(18,50)
r, err := db.Table("user").Where("age IN(?,?)", 18, 50).Count()
r, err := db.Table("user").Where("age", g.Slice{18, 50}).Count()
使用任意map
参数类型。
// SELECT * FROM user WHERE gender=1 AND uid IN(100,10000,90000)
r, err := db.Table("user").Where(g.Map{
"gender" : 1,
"uid" : g.Slice{100,10000,90000},
}).All()
使用struct
参数类型,注意查询条件的顺序和struct
的属性定义顺序有关。
type User struct {
Id []int `orm:"uid"`
Gender int `orm:"gender"`
}
// SELECT * FROM `user` WHERE uid IN(100,10000,90000) AND gender=1
r, err := db.Table("user").Where(User{
"gender" : 1,
"uid" : []int{100, 10000, 90000},
}).All()
为提高易用性,当传递的slice
参数为空或nil
时,查询并不会报错,而是转换为一个false
条件语句。
Code Block |
---|
|
// SELECT * FROM `user` WHERE 0=1
r, err := db.Table("user").Where("uid", g.Slice{}).All()
r, err := db.Table("user").Where("uid", nil).All() |
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了常用条件方法WhereIn/WhereNotIn/WhereOrIn/WhereOrNotIn
方法,用于常用的In
查询条件过滤。方法定义如下:
Code Block |
---|
|
func (m *Model) WhereIn(column string, in interface{}) *Model
func (m *Model) WhereNotIn(column string, in interface{}) *Model
func (m *Model) WhereOrIn(column string, in interface{}) *Model
func (m *Model) WhereOrNotIn(column string, in interface{}) *Model |
使用示例:
Code Block |
---|
|
// SELECT * FROM `user` WHERE `gender`=1 AND `type` IN(1,2,3)
db.Model("user").Where("gender", 1).WhereIn("type", g.Slice{1,2,3}).All()
// SELECT * FROM `user` WHERE `gender`=1 AND `type` NOT IN(1,2,3)
db.Model("user").Where("gender", 1).WhereNotIn("type", g.Slice{1,2,3}).All()
// SELECT * FROM `user` WHERE `gender`=1 OR `type` IN(1,2,3)
db.Model("user").Where("gender", 1).WhereOrIn("type", g.Slice{1,2,3}).All()
// SELECT * FROM `user` WHERE `gender`=1 OR `type` NOT IN(1,2,3)
db.Model("user").Where("gender", 1).WhereOrNotIn("type", g.Slice{1,2,3}).All() |
3. like
查询
// SELECT * FROM `user` WHERE name like '%john%'
r, err := db.Table("user").Where("name like ?", "%john%").All()
// SELECT * FROM `user` WHERE birthday like '1990-%'
r, err := db.Table("user").Where("birthday like ?", "1990-%").All()
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了常用条件方法WhereLike/WhereNotLike/WhereOrLike/WhereOrNotLike
方法,用于常用的Like
查询条件过滤。方法定义如下:
Code Block |
---|
|
func (m *Model) WhereLike(column string, like interface{}) *Model
func (m *Model) WhereNotLike(column string, like interface{}) *Model
func (m *Model) WhereOrLike(column string, like interface{}) *Model
func (m *Model) WhereOrNotLike(column string, like interface{}) *Model |
使用示例:
Code Block |
---|
|
// SELECT * FROM `user` WHERE `gender`=1 AND `name` LIKE 'john%'
db.Model("user").Where("gender", 1).WhereLike("name", "john%").All()
// SELECT * FROM `user` WHERE `gender`=1 AND `name` NOT LIKE 'john%'
db.Model("user").Where("gender", 1).WhereNotLike("name", "john%").All()
// SELECT * FROM `user` WHERE `gender`=1 OR `name` LIKE 'john%'
db.Model("user").Where("gender", 1).WhereOrLike("name", "john%").All()
// SELECT * FROM `user` WHERE `gender`=1 OR `name` NOT LIKE 'john%'
db.Model("user").Where("gender", 1).WhereOrNotLike("name", "john%").All() |
4. min/max/avg/sum
我们直接将统计方法使用在Fields
方法上,例如:
Code Block |
---|
|
// SELECT MIN(score) FROM `user` WHERE `uid`=1
db.Table("user").Fields("MIN(score)").Where("uid", 1).Value()
// SELECT MAX(score) FROM `user` WHERE `uid`=1
db.Table("user").Fields("MAX(score)").Where("uid", 1).Value()
// SELECT AVG(score) FROM `user` WHERE `uid`=1
db.Table("user").Fields("AVG(score)").Where("uid", 1).Value()
// SELECT SUM(score) FROM `user` WHERE `uid`=1
db.Table("user").Fields("SUM(score)").Where("uid", 1).Value() |
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了常用统计方法Min/Max/Avg/Sum
方法,用于常用的字段统计查询。方法定义如下:
Code Block |
---|
|
func (m *Model) Min(column string) (float64, error)
func (m *Model) Max(column string) (float64, error)
func (m *Model) Avg(column string) (float64, error)
func (m *Model) Sum(column string) (float64, error) |
上面的示例使用快捷统计方法改造后:
Code Block |
---|
|
// SELECT MIN(`score`) FROM `user` WHERE `uid`=1
db.Table("user").Where("uid", 1).Min("score")
// SELECT MAX(`score`) FROM `user` WHERE `uid`=1
db.Table("user").Where("uid", 1).Max("score")
// SELECT AVG(`score`) FROM `user` WHERE `uid`=1
db.Table("user").Where("uid", 1).Avg("score")
// SELECT SUM(`score`) FROM `user` WHERE `uid`=1
db.Table("user").Where("uid", 1).Sum("score") |
5. count
查询
// SELECT COUNT(1) FROM `user` WHERE `birthday`='1990-10-01'
db.Table("user").Where("birthday", "1990-10-01").Count()
// SELECT COUNT(uid) FROM `user` WHERE `birthday`='1990-10-01'
db.Table("user").Fields("uid").Where("birthday", "1990-10-01").Count()
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了一个按照字段进行Count
的常用方法CountColumn
。方法定义如下:
Code Block |
---|
|
func (m *Model) CountColumn(column string) (int, error) |
使用示例:
Code Block |
---|
|
db.Table("user").Where("birthday", "1990-10-01").CountColumn("uid") |
6. distinct
查询
// SELECT DISTINCT uid,name FROM `user`
db.Table("user").Fields("DISTINCT uid,name").All()
// SELECT COUNT(DISTINCT uid,name) FROM `user`
db.Table("user").Fields("DISTINCT uid,name").Count()
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了一个字段唯一性过滤标记方法Distinct
。方法定义如下:
Code Block |
---|
|
func (m *Model) Distinct() *Model |
使用示例:
Code Block |
---|
|
// SELECT COUNT(DISTINCT `name`) FROM `user`
db.Table("user").Distinct().CountColumn("name")
// SELECT COUNT(DISTINCT uid,name) FROM `user`
db.Table("user").Distinct().CountColumn("uid,name") |
7. between
查询
// SELECT * FROM `user ` WHERE age between 18 and 20
db.Table("user").Where("age between ? and ?", 18, 20).All()
从goframe v1.15.7
版本开始,goframe
的ORM
同时也提供了常用条件方法WhereBetween/WhereNotBetween/WhereOrBetween/WhereOrNotBetween
方法,用于常用的Between
查询条件过滤。方法定义如下:
Code Block |
---|
|
func (m *Model) WhereBetween(column string, min, max interface{}) *Model
func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model
func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model
func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model |
使用示例:
Code Block |
---|
|
// SELECT * FROM `user` WHERE `gender`=0 AND `age` BETWEEN 16 AND 20
db.Model("user").Where("gender", 0).WhereBetween("age", 16, 20).All()
// SELECT * FROM `user` WHERE `gender`=0 AND `age` NOT BETWEEN 16 AND 20
db.Model("user").Where("gender", 0).WhereNotBetween("age", 16, 20).All()
// SELECT * FROM `user` WHERE `gender`=0 OR `age` BETWEEN 16 AND 20
db.Model("user").Where("gender", 0).WhereOrBetween("age", 16, 20).All()
// SELECT * FROM `user` WHERE `gender`=0 OR `age` NOT BETWEEN 16 AND 20
db.Model("user").Where("gender", 0).WhereOrNotBetween("age", 16, 20).All() |
8. null
查询
从goframe v1.15.7
版本开始,goframe
的ORM
提供了常用条件方法WhereNull/WhereNotNull/WhereOrNull/WhereOrNotNull
方法,用于常用的Null
查询条件过滤。方法定义如下:
Code Block |
---|
|
func (m *Model) WhereNull(columns ...string) *Model
func (m *Model) WhereNotNull(columns ...string) *Model
func (m *Model) WhereOrNull(columns ...string) *Model
func (m *Model) WhereOrNotNull(columns ...string) *Model |
使用示例:
Code Block |
---|
|
// SELECT * FROM `user` WHERE `created_at` > '2021-05-01 00:00:00' AND `inviter` IS NULL
db.Model("user").Where("created_at>?", gtime.New("2021-05-01")).WhereNull("inviter").All()
// SELECT * FROM `user` WHERE `created_at` > '2021-05-01 00:00:00' AND `inviter` IS NOT NULL
db.Model("user").Where("created_at>?", gtime.New("2021-05-01")).WhereNotNull("inviter").All()
// SELECT * FROM `user` WHERE `created_at` > '2021-05-01 00:00:00' OR `inviter` IS NULL
db.Model("user").Where("created_at>?", gtime.New("2021-05-01")).WhereOrNull("inviter").All()
// SELECT * FROM `user` WHERE `created_at` > '2021-05-01 00:00:00' OR `inviter` IS NOT NULL
db.Model("user").Where("created_at>?", gtime.New("2021-05-01")).WhereOrNotNull("inviter").All() |
同时,这几个方法的参数支持多个字段输入,例如:
Code Block |
---|
|
// SELECT * FROM `user` WHERE `created_at` > '2021-05-01 00:00:00' AND `inviter` IS NULL AND `creator` IS NULL
db.Model("user").Where("created_at>?", gtime.New("2021-05-01")).WhereNull("inviter", "creator").All() |
Panel |
---|
|
toc