基础示例:
import (
"fmt"
)
func GetUserDetailSql(tx *gorm.DB,id int,data model)(sql string){
var query = tx.Session(&gorm.Session{DryRun: true})
var querySmt= query.Where("id = ?", id).First(&data).Statement
sql=sqlStm.Dialector.Explain(sqlStm.SQL.String(), sqlStm.Vars...)
fmt.Println("执行的sql:",sql)
}
注意事项:
- 执行前需要事先声明Session,将DryRun设置为true;
- 执行完First、Find、Delete 等方法后拿到Statement对象去获取sql语句;
- DryRun设置为true以后,只会组建SQL语句,不会执行数据库操作。
使用技巧
此方法可以配合scopes组建复杂的SQL查询语句
type QueryUserTableBuidler{
SelectFileds []string
}
func (q *QueryUserTableBuidler)Build(params *queryUserParams,tx *gorm.DB)(sql string,err error){
var baseTable = `SELECT su.id user_id, rn.name real_name, su.tel_num, rn.id_num FROM sys_suer su
Left JOIN real_name rn ON su.real_name_id = rn.id AND rn.deleted_at =0
WHERE su.deleted_at =0`
//处理基础表的字段筛选
if params.IdNum!= "" {
base += fmt.Sprintf("AND su.id_num = '%s'", params.IdNum)
}
if params.Sex != "" {
base += fmt.Sprintf("AND rn.sex = '%s'", params.Sex)
}
//生成基础表t
tx.Table(fmt.Sprintf("(%s) AS t"),baseTable )
q.SelectFields = append(q.SelectFields, "t.user_id","t.real_name","t.tel_num","t.id_num")
//加载关联表
tx = tx.Scopes(
q.JoinsShowStatScope(),//可以添加多个关联查询
)
//生成Sql
var query = tx.Session(&gorm.Session{DryRun: true})
var querySmt= query.Select(strings.Join(q.SelectFields,",")).Where("id = ?", id).First(&view.UserStat).Statement
sql=sqlStm.Dialector.Explain(sqlStm.SQL.String(), sqlStm.Vars...)
fmt.Println("sql:",sql)
return
}
func (q*QueryUserTableBuidler) JoinsShowStatScope(params *queryUserParams) func(tx*gorm.DB) *gorm.DB {
//select中添加此关联sql对外的字段
q.SelectFields = append(q.SelectFields, `IFNULL(show_stat.show_count,0) show_count`)
return func(tx*gorm.DB) *gorm.DB {
var sql=`LEFT JOIN ( SELECT user_id,COUNT(id) show_count FROM user_show WHERE IFNULL(deleted_at,0)=0 AND is_show >= 3 %s GROUP BY user_id ) show_stat ON t.user_id = show_stat.artist_uid`
var where string
if params.UserId!=0{
where +=fmt.Sprintf("AND user_id = %d",params.UserId)
}
sql=fmt.Sprintf(sql,where)
tx=tx.Joins(sql)
return tx
}
}
使用
func QueryUserStat(params *queryUserParams)(res []*view.UserStat,err error)
sqlRaw ,err := new(QueryUserTableBuidler).Build(params, db.DB)
if err!=nil{
return err
}
tx = db.DB.Table(fmt.Sprintf("(SELECT * FROM (%s) tt ) tt", sqlRaw ))
if params.IdNum!=""{
tx=tx.Where("id_num = ?",params.IdNum)
}
err=tx.Find(&res).Err
return
- 模块化的JOIN语句 ,易于组装,适合快速的功能迭代。可以快速对Join语句进行增删。
- 易于优化SQL的执行速度。示例中的QueryUserTableBuidler,使用了查询参数,对局部sql进行了优化,从而提升了查询速度。