MySQL模糊查询通配符转义总结

一、问题背景

系统测试过程中,测试同学反馈搜索框输入"%"或"_"进行模糊查询后,查询结果不正确;搜索期望结果是仅包含"%"或"_"的记录。

二、原因

模糊查询是一种通过模糊条件来匹配数据库中数据的查询方法,通常会使用以下两种通配符进行数据匹配。

  • %: 表示零个或多个字符。例如,%cat% 匹配包含 "cat" 的任何字符串。
  • _: 表示一个单一的字符。例如,h_t 匹配 "hat"、"hot" 等。

如果没对通配符进行处理而直接进行查询时,它代表的特殊含义将会使得查询结果不正确。

三、解决思路

想要查询包含 "%"或"_" 字符的字段值,但又不希望它们被解释为通配符时,可以使用转义字符"\" (在MySQL中,默认使用"\"用作转义字符)来取消这些字符的特殊含义。

四、解决方法

1、\ 反斜杠转义:

这里我封装好了一个工具类,当某个查询条件需要进行模糊查询时,先对查询条件进行预处理,然后再塞到SQL中。

(1)工具类代码:

import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;public class SqlLikeUtil {private static final char MYSQL_WILDCARD_PERCENTAGE = '%';private static final char MYSQL_WILDCARD_UNDERSCORE = '_';private static final char MYSQL_DEFAULT_ESCAPE = '\\';private static final char[] MYSQL_WILDCARDS = new char[]{'%', '_', '\\'};public SqlLikeUtil() {}public static String genMysqlLikedString(String str) {return genMysqlLikedString(str, true, true);}public static String genMysqlLikedPrefixString(String str) {return genMysqlLikedString(str, true, false);}public static String genMysqlLikedString(String str, boolean prefixMatch, boolean suffixMatch) {if (str == null) {return null;} else {String escaped = escapeChars(MYSQL_WILDCARDS, '\\', str);StringBuilder builder = new StringBuilder();if (suffixMatch) {builder.append('%');}builder.append(escaped);if (prefixMatch) {builder.append('%');}return builder.toString();}}private static String escapeChars(char[] chars, char escape, String str) {if (chars != null && chars.length != 0 && str != null) {Escapers.Builder builder = Escapers.builder();char[] var4 = chars;int var5 = chars.length;for(int var6 = 0; var6 < var5; ++var6) {char c = var4[var6];String replacement = new String(new char[]{escape, c});builder.addEscape(c, replacement);}Escaper escaper = builder.build();String result = escaper.escape(str);return result;} else {return str;}}}

代码逻辑解释:创建转义器对象,将"%", "_", "\\" 加入到转义器,使用这个转义器即可对字段值进行特殊字符的转义。

这里重点说明一下,数据库中的"\"在Java代码中要表示为 "\\";其次,为什么我们需要对 "\\" 也进行转义。

如果我们的查询条件为name = "\",但此时并未对其进行转义,那么对应的SQL应为:

select * from test where name like '%\%';

这段SQL的查询含义为查询任意字符开头,以"%"结尾的值,与我们设想的不符,正确的SQL应为:

select * from test where name like '%\\%';

这样 "\" 就可被作为普通字符进行查询了。

(2)使用示例

String name = SqlLikeUtil.genMysqlLikedString(req.getName());

注:上述SqlLikeUtil.genMysqlLikedString()方法的调用会使得name值前后被 "%" 包围,所以我们在使用like进行查询条件拼接时,只需直接取值即可;如果想对字段值前后拼接"%"进行控制,可以调用genMysqlLikedString()重载的方法,指定前缀、后缀。

2、指定转义字符进行转义:

在解决问题的过程中,我发现并不是只可以使用 "\" 进行转义,可以使用ESCAPE关键字在SQL中指定转义字符。

ESCAPE 是一个用于指定转义字符的关键字,ESCAPE 关键字允许你指定一个转义字符,用于转义模糊查询中的特殊字符。比如,在模糊查询中使用了 ESCAPE '/',这意味着斜杠 / 被指定为转义字符。在这个例子中,%/_ 表示任意字符和任意单个字符,而 ESCAPE '/' 指定了斜杠 / 为转义字符。因此,/% 和 /_ 会被解释为普通字符,而不是通配符。

(1)工具类代码:

import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;public class SqlLikeUtil {private static final char MYSQL_WILDCARD_PERCENTAGE = '%';private static final char MYSQL_WILDCARD_UNDERSCORE = '_';private static final char MYSQL_DEFAULT_ESCAPE = '\\';private static final char[] MYSQL_WILDCARDS = new char[]{'%', '_', '/'};public SqlLikeUtil() {}public static String genMysqlLikedString(String str) {return genMysqlLikedString(str, true, true);}public static String genMysqlLikedPrefixString(String str) {return genMysqlLikedString(str, true, false);}public static String genMysqlLikedString(String str, boolean prefixMatch, boolean suffixMatch) {if (str == null) {return null;} else {String escaped = escapeChars(MYSQL_WILDCARDS, '/', str);StringBuilder builder = new StringBuilder();if (suffixMatch) {builder.append('%');}builder.append(escaped);if (prefixMatch) {builder.append('%');}return builder.toString();}}private static String escapeChars(char[] chars, char escape, String str) {if (chars != null && chars.length != 0 && str != null) {Escapers.Builder builder = Escapers.builder();char[] var4 = chars;int var5 = chars.length;for(int var6 = 0; var6 < var5; ++var6) {char c = var4[var6];String replacement = new String(new char[]{escape, c});builder.addEscape(c, replacement);}Escaper escaper = builder.build();String result = escaper.escape(str);return result;} else {return str;}}}

说明:与使用 "\" 进行转义不同的是,在使用工具类对查询条件转义后,还需要在SQL中加ESCAPE '/',例如:where name like #{name} ESCAPE '/'。

如果没有其他场景要求的话,使用"\"进行转义更方便。

最后, SqlLikeUtil工具类可能不太完善,但可以给大家提供一个思路,大家可以根据自己的实际想法与需求完善这个工具类,希望我的思路可以帮到大家~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/650376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue开发的PC端项目使用postcss-to-viewport适配移动端

开发PC端项目&#xff0c;突然有一天产品说&#xff0c;手机打开样式错乱了&#xff0c;适配一下 1. 安装依赖 "postcss-px-to-viewport": "^1.1.1",2. 项目根目录创建并配置postcss.config.js 文件 module.exports {plugins: {autoprefixer: {},postcs…

华为云WAF,开启web网站的专属反爬虫防护罩

背景 从保护原创说起 作为一个原创技术文章分享博主&#xff0c;日常除了Codeing就是总结Codeing中的技术经验。 之前并没有对文章原创性的保护意识&#xff0c;直到在某个非入驻的平台看到了我的文章&#xff0c;才意识到&#xff0c;辛苦码字、为灵感反复试验创作出来的文…

(Unity)C# 中的字符串格式化

前言 在软件开发中&#xff0c;理解和掌握字符串的格式化及调试技巧对于编写高效和可维护的代码至关重要。 字符串插值 ($ 符号) 在 C# 中&#xff0c;字符串插值是通过在字符串前加 $ 符号来实现的。这允许我们将变量、表达式或函数调用直接嵌入到字符串中。 string name &qu…

JavaScript模块系统入门教程

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ 目录 ✨ 前言 ✨ 正文 一、模块 (Module) 简介 什么是模块 导出与导入 默…

QGIS编译(跨平台编译)之二十四:libbz2编译(Windows、Linux、MacOS环境下编译)

文章目录 1、libbz2介绍2、文件下载3、Linux下编译4、MacOS下编译5、Windows下编译1、libbz2介绍 bzip2是一个基于Burrows-Wheeler 变换的无损压缩软件,压缩效果比传统的LZ77/LZ78压缩算法来得好。它是一款免费软件。可以自由分发免费使用。 bzip2能够进行高质量的数据压缩。…

【代码随想录15】110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和

目录 110. 平衡二叉树题目描述参考代码 257. 二叉树的所有路径题目描述参考代码 404.左叶子之和题目描述参考代码 110. 平衡二叉树 题目描述 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树…

AI数字人-数字人视频创作数字人直播效果媲美真人

在科技的不断革新下&#xff0c;数字人技术正日益融入到人们的生活中。近年来&#xff0c;随着AI技术的进一步发展&#xff0c;数字人视频创作领域出现了一种新的创新方式——AI数字人。数字人视频通过AI算法生成虚拟主播&#xff0c;其外貌、动作、语音等方面可与真实人类媲美…

huggingface高速下载模型的实战代码

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

Compose | UI组件(一) | Modifier修饰符

文章目录 Modifier修饰符-简介Modifier修饰符 - sizeModifier修饰符 - backgroundModifier修饰符 - fillMaxSizeModifier修饰符 - border 和 paddingModifier修饰符 - offset 总结 Modifier修饰符-简介 Modifier通过链式调用方式为所有Compose组件设置样式&#xff08;大小&am…

Neo4j 国内镜像下载与安装

Neo4j 5.x 简体中文版指南 社区版&#xff1a;https://neo4j.com/download-center/#community 链接地址&#xff08;Linux版&#xff09;&#xff1a;https://neo4j.com/artifact.php?nameneo4j-community-3.5.13-unix.tar.gz 链接地址&#xff08;Windows&#xff09;&#x…

蓝桥杯省赛无忧 编程13 肖恩的投球游戏

#include <iostream> #include <vector> using namespace std; int main() {int n, q;cin >> n >> q;vector<int> a(n 1);vector<int> diff(n 2, 0); // 初始化差分数组// 读取初始球数&#xff0c;构建差分数组for (int i 1; i < …

Go 从标准输入读取数据

fmt.Scan系列 fmt.Scan函数定义如下&#xff1a; // Scan scans text read from standard input, storing successive space-separated values into successive arguments. // Newlines count as space. // It returns the number of items successfully scanned. // If tha…

DS:单链表的实现(超详细!!)

创作不易&#xff0c;友友们点个三连吧&#xff01; 在博主的上一篇文章中&#xff0c;很详细地介绍了顺序表实现的过程以及如何去书写代码&#xff0c;如果没看过的友友们建议先去看看哦&#xff01; DS&#xff1a;顺序表的实现&#xff08;超详细&#xff01;&#xff01;&…

JAVA大学生兼职平台后台管理

运行环境&#xff1a; tomcat7.0jdk1.7或以上 eclipse或idea 使用技术&#xff1a; springboot 功能描述&#xff1a; 求职人员 注册&#xff0c;登录 选定登录角色&#xff08;1、兼职人员2、发布兼职招聘人员&#xff09; 书写简历&#xff0c;上传学生证照片&#…

ADB的配置和使用 ADB操作手机-1

「adb」即 Android Debug Bridge &#xff0c;亦称安卓调试桥&#xff0c;是谷歌为安卓开发者提供的开发工具之一&#xff0c;可以让你的电脑以指令窗口的方式控制手机。 可以在安卓开发者网页中的 SDK 平台工具页面下直接下载对应系统的 adb 配置文件&#xff0c;大小只有几十…

代码随想录训练营第三十二天打卡|122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

122.买卖股票的最佳时机II 1.做的时候感觉不难&#xff0c;自己也AC了&#xff0c;但是一下子说清楚为什么这样做并不容易。思考之后&#xff0c;我得到了一个自己感觉还算形象的解释。股票价格走势是一个折线图&#xff0c;两天之间的股票价格构成一条折线。我们只要在每一条…

力扣每日一题 ---- 1039. 多边形三角剖分的最低得分

这题的难点在哪部分呢&#xff0c;其实是怎么思考。这道题如果之前没做过类似的话&#xff0c;还是很难看出一些性质的&#xff0c;这题原本的话是没有图片把用例显示的这么详细的。这题中有个很隐晦的点没有说出来 剖出来的三角形是否有交叉&#xff0c;这题中如果加一个三角…

网络防御——NET实验

一、实验拓扑 二、实验要求 1、生产区在工作时间&#xff08;9&#xff1a;00---18&#xff1a;00&#xff09;内可以访问服务区&#xff0c;仅可以访问http服务器&#xff1b; 2、办公区全天可以访问服务器区&#xff0c;其中&#xff0c;10.0.2.20可以访问FTP服务器和HTTP服…

水文模型SWMM与LisFlood耦合(pdf文档、软件见资源)

总技术路线图 INP生成图解 文献&#xff1a;面向服务的Web-SWMM构建研究 regardingINP为ArcGIS Pro项目 1.SWMM模型数据准备与参数设置 1.子汇水区 文件位于&#xff1a;beforeGenerateINP/generateSub.py&#xff08;一级划分&#xff09; 问题&#xff1a; 水文分析阈值划…

命令行安装vant2项目

声明&#xff1a;原文参考链接出自&#xff1a;ERROR in ./node_modules/vant export ‘createVNode‘ (imported as ‘_createVNode‘) was not found in ‘vue_error in node_modules/vant/lib/overlay/overlay.d.t-CSDN博客 已经安装Vant,但是引用Vant里面组件库时候报错&a…