gorm中多表联合查询,我们可以使用Joins来完成,这个Joins方法很灵活,我们可以非常方便的多多表进行联合查询, 我们先来看看这个方法的官方定义和使用示例:
Joins方法定义和使用示例
当然我们这里要说的使用方式是官方示例里面没有的,有的我们就不重复废话了。
从上面的方法定义我们可以看到,这个Joins的第一个参数query string 他就是一个查询字符串, 第二个参数是可变参数, 从这个参数定义就可以看出,这里的第一个参数query 就是我们需要进行多表链接的查询参数,这里的查询参数可以是任何的SQL支持的链接查询语句,如 LEFT JOIN , RIGHT JOIN , INNER JOIN, FULL JOIN等。
gorm中的这个Joins方法,我们可以直接将我们需要的链接方式和链接条件都写在这个查询字符串里面即可,如果有参数可以跟在后面,参数可以使用问号? 占位符方式 或者 @xxx 命名参数方式传递。
LEFT JOIN 左链接使用示例
// 获取用户拥有的角色ID和值的对象数组
func (s *roleSvc) GetRoleIdsValByUid(c *ginx.XContext, uid int32) ([]int64, error) {
var roleIds []int64
m := global.GetTx("sys_role c").Select("c.role_id")
m = m.Joins("LEFT JOIN sys_user_role ur on ur.role_id = c.role_id")
m = m.Joins("LEFT JOIN sys_user u on u.uid = ur.uid")
m = m.Where("c.del_flag = '0' and u.del_flag = '0'")
m = m.Where("ur.uid = ?", uid)
err := m.Pluck("c.role_id", &roleIds).Error
if err != nil {
return nil, myerror.New("未查询到用户角色数据数据 " + err.Error())
}
return roleIds, nil
}
其他的链接方式使用都是一样的,只是不同的链接方式输出的结果不一样而已。
其语法一般为: 链接方式 表名 别名 ON 链接条件 如: LEFT JOIN sys_user u on u.uid = ur.uid
常用SQL JOIN的语义
- LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行 这个用得最多
- RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
- INNER JOIN:如果表中有至少一个匹配,则返回行
- FULL JOIN:只要其中一个表中存在匹配,则返回行
Gorm Joins链接代码参考
// Joins specify Joins conditions
//
// db.Joins("Account").Find(&user)
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
// db.Joins("Account", DB.Select("id").Where("user_id = users.id AND name = ?", "someName").Model(&Account{}))
func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
return joins(db, clause.LeftJoin, query, args...)
}
// InnerJoins specify inner joins conditions
// db.InnerJoins("Account").Find(&user)
func (db *DB) InnerJoins(query string, args ...interface{}) (tx *DB) {
return joins(db, clause.InnerJoin, query, args...)
}
func joins(db *DB, joinType clause.JoinType, query string, args ...interface{}) (tx *DB) {
tx = db.getInstance()
if len(args) == 1 {
if db, ok := args[0].(*DB); ok {
j := join{
Name: query, Conds: args, Selects: db.Statement.Selects,
Omits: db.Statement.Omits, JoinType: joinType,
}
if where, ok := db.Statement.Clauses["WHERE"].Expression.(clause.Where); ok {
j.On = &where
}
tx.Statement.Joins = append(tx.Statement.Joins, j)
return
}
}
tx.Statement.Joins = append(tx.Statement.Joins, join{Name: query, Conds: args, JoinType: joinType})
return
}
总结
Gorm中官方只提供了2个相关的Join方法,一个就是Joins, 另外一个时 InnerJoins, 他们最终都调用的joins方法。 我们可根据我们的业务需求直接将我们需要的链接查询语句放到这里的query参数里面, gorm就会为我们生成对应的查询SQL。 需要注意的是,这里的Joins方法,如果我们指定了链接条件, 则这里就必须要手动指定链接方式,如.Joins("LEFT JOIN sys_user_role ur on ur.role_id = c.role_id")