Skip to content

SubWhere安全子查询

Tuuz edited this page Aug 9, 2023 · 5 revisions

使用方法: 1.创建语句,使用buildsql创建语句 2.使用db.SubWhere(field查询字段, condition查询模式, sql子查询语句,args子查询绑定参数) 完成子查询绑定 3.继续使用连续方法做其他查询 4.get或find方法取出数据

安全问题: 查看了TP的子查询方法,因为没有执行stmt,有被注入的可能,所以在设计sql方法的时候,特别考量了安全问题,因此你的每一次subQuery的生成和执行,均需要使用BuildSql方法生成语句和查询绑定条件才能保证安全

简单的例子:

我希望通过SchoolId查到对应学校的AreaId(区域ID),再通过AreaId反查这个区域下有哪几所学校

这将会生成一条语句:

SELECT * FROM `ps_school` WHERE `area_id` = (SELECT area_id FROM `ps_school` WHERE `id` = ? and `domain` = ?)

因为使用了参数化查询,所以可以在此基础上构建安全的查询方式

func Api_select_area_bySchoolId(id any) []gorose.Data {
	db := tuuz.Db().Table(Table)
	db.Fields("area_id")
	db.Where("id", id)
	db.Where("domain", "minshen")
	sql, args, err := db.BuildSql("select")
	if err != nil {
		Log.DBrrsql(err, db, tuuz.FUNCTION_ALL())
		return nil
	}
	db2 := tuuz.Db().Table(Table)
	db2.SubWhere("area_id", "=", sql, args)
	ret, err := db2.Get()
	fmt.Println(db2.LastSql())
	if err != nil {
		Log.DBrrsql(err, db, tuuz.FUNCTION_ALL())
		return nil
	} else {
		return ret
	}
}

performance

这个查询方式将有概率破坏IndexCondition,这将大大降低你程序的性能,但是这能降低Mysql到你程序间的TCP浪费,所以使用程序法还是DB法解决问题,需要考量你当前的需求和数据量。

  • 大库数据量大的情况下,优先考虑使用程序法
  • 过程多,多次回转查询需求或降级In查询,可以考虑使用SubWhere方法
  • 小库小数据量大查询量,有回转查询的需求,可以使用SubWhere方法
  • Index Condition 降级,Where Condition降级,数据量小的情况下,并有降低代码量的需求,优先使用SubWhere方法