特殊字符转义与联合列表模糊查询

文章讲述了在Go语言中如何处理Mysql查询时的特殊字符转义问题,包括使用MysqlSpecialCharHandle函数遍历结构体并转义字符串字段,以及结合反射库处理联合列表的模糊查询。示例代码展示了如何构建SQL语句并执行安全的查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、参数判断,如果有特殊字符,进行转义操作

func sqlAgencyListFindParam(agency AgencyList) string {
	// 定义变量
	sql := ""
	// 参数判断,如果有特殊字符,进行转义操作
	utils.MysqlSpecialCharHandle(&agency)  //此处传入的是指针,若函数中的参数已经是指针,则无需再带&
	if agency.Name != "" {
		sql += " name LIKE '%" + agency.Name + "%' AND "
	}
	
	return sql
}

///

// @title                     MysqlSpecialCharHandle
// @description               Mysql 数据库查询,字符串字段需要校验,避免出现特殊字符,如果有特殊字符,进行转义操作
// @param     s               interface{}           结构体变量
// @return
func MysqlSpecialCharHandle(s interface{}) {
	log.Info("MysqlSpecialCharHandle")
	prval := reflect.ValueOf(s)
	num := prval.Elem().NumField()
	// TODO 遍历结构体
	for i := 0; i < num; i++ {
		if prval.Elem().Field(i).Kind() == reflect.String {
			srcfield := prval.Elem().Field(i).String()
			realescapestring := mysqlRealEscapeString(srcfield)
			prval.Elem().Field(i).SetString(realescapestring)
		}
	}
}

// @title    mysqlRealEscapeString
// @description   MySql字符转义
// https://www.cnblogs.com/end/archive/2011/04/01/2002516.html
// \0	ASCII 0(NUL)字符。
// \'	单引号(‘'’)。
// \"	双引号(‘"’)。
// \b	退格符。
// \n	换行符。
// \r	回车符。
// \t	tab字符。
// \Z	ASCII 26(控制(Ctrl)-Z)。该字符可以编码为‘\Z’,以允许你解决在Windows中ASCII 26代表文件结尾这一问题。(如果你试图使用mysql db_name < file_name,ASCII 26会带来问题)。
// \\	反斜线(‘\’)字符。
// \%	‘%’字符: 包含零个或更多字符的任意字符串。
// \_	‘_’字符: 任何单个字符。
// [ ]	指定范围(例如 [a-f])或集合(例如 [abcdef])内的任何单个字符。
// [^]	不在指定范围(例如 [^a - f])或集合(例如 [^abcdef])内的任何单个字符。
func mysqlRealEscapeString(field string) string {
	log.Info("mysqlRealEscapeString field:" + field)

	field = strings.Replace(field, "\\", "\\\\\\\\\\\\\\\\", -1) // -1 全部替换
	//field = strings.Replace(field, "0", "\\0", -1) // -1 全部替换
	field = strings.Replace(field, "'", "\\'", -1) // -1 全部替换
	//field = strings.Replace(field, "\"", "\\\"", -1)   // -1 全部替换
	field = strings.Replace(field, "\b", "\\\\b", -1)    // -1 全部替换
	field = strings.Replace(field, "\n", "\\\\n", -1)    // -1 全部替换
	field = strings.Replace(field, "\r", "\\\\r", -1)    // -1 全部替换
	field = strings.Replace(field, "\t", "\\\\t", -1)    // -1 全部替换
	field = strings.Replace(field, "\\Z", "\\\\Z", -1)   // -1 全部替换
	field = strings.Replace(field, "%", "\\%", -1)       // -1 全部替换
	field = strings.Replace(field, "_", "\\_", -1)       // -1 全部替换
	reg, err := regexp.Compile("\\[(^)?[\\s\\S]{0,}\\]") // 校验 []
	if err != nil {
		log.Error("error(%v)", err)
		return field
	}
	if reg.MatchString(field) {
		field = strings.Replace(field, "[", "\\[", -1) // -1 全部替换
	}

	log.Info("mysqlRealEscapeString newField:" + field)
	return field
}

 二、联合列表模糊查询

第一种:组合sql语句

// 用户列表
func (r *userRepo) UserList(ctx context.Context, user *biz.UserList) ([]*biz.UserListRes, uint64, error) {
	var (
		ttl         int64
		userListRes []*biz.UserListRes
	)
	//
	sqlParam := sqlUserListFindParam(user)
	//res := r.data.db.Table("agency").
    res := r.data.db.Model(&Agency{}).
		Select("user.username, user.mobile, agency.name as agencyname, user.id as UserID").
		Joins("join user on " +
			"user.agency_id = agency.id").
		Where(sqlParam + "user.deleted_at IS NULL" +
			" AND " + "agency.deleted_at IS NULL").
		Count(&ttl).Order("user.id desc").Limit(int(user.PageSize)).Offset(int((user.Page - 1) * user.PageSize)).
		Find(&userListRes)

	if res.Error != nil {
		return nil, uint64(ttl), errors.New(utils.AGENCY_LIST, "", "查询失败")
	}
	return userListRes, uint64(ttl), nil
}

func sqlUserListFindParam(user *biz.UserList) string {
	// 定义变量
	sql := ""
	// 参数判断,如果有特殊字符,进行转义操作
	utils.MysqlSpecialCharHandle(user)
	if user.Username != "" {
		sql += " user.username LIKE '%" + user.Username + "%' AND "
	}
	if user.Mobile != "" {
		sql += " user.mobile LIKE '%" + user.Mobile + "%' AND "
	}
	//todo
	if user.Agencyname != "" {
		sql += " agency.name LIKE '%" + user.Agencyname + "%' AND "
	}
	return sql
}

第二种:组合查询语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值