##模糊查询使用%和_特殊符号进行查询的解决方法
1、背景:
因为%以及_在数据库查询中本身就是在进行模糊查询,如果查询条件包含%以及_,会使SQL失效,因此需要进行转义处理,以下是关于如何处理的说明。
2、处理思路:
将含有特殊符号的查询条件按照特殊字符拆分后拼接上转义字符,并在SQL语句中使用 escape 关键字声明转义字符,
3、代码处理:
使用代码按照特殊字符进行拆分时因为不确定特殊字符的位置,所以需要区分三种情况: 1、查询条件以特殊字符结尾的,因为特殊字符后面没有内容,不会进行拆分,所以不需要再去掉末尾的字符; 2、查询条件仅包含特殊字符的,直接按照字符个数拼接转义符号; 3、查询条件开始或者中间位置是特殊字符的,按照正常拆分数量拼接转义符号.
/**
* 对包含% 或者_特殊字符的数据增加转义符号.
*/
public static String transContainsSpeChar(String data,String speChar){
StringBuilder builder = new StringBuilder();
String[] split = data.split(speChar);
//根据特殊字符查分,拼接转义字符
for (int i = 0; i < split.length; i++) {
builder.append(split[i]).append("\\").append(speChar);
}
//以特殊字符结尾不需要删除末尾字符串
if (!data.endsWith(speChar)){
builder.delete(builder.length() - 2, builder.length());
}
//仅包含特殊字符
if(isAllSpeChar(data,speChar)){
for (int i = 0; i < data.length(); i++) {
builder.append("\\").append(speChar);
}
}
return builder.toString();
}
/**
* 判断字符串是否只包含 %或者 _.
*/
public static boolean isAllSpeChar(String str,String speChar) {
String patStr = "^"+speChar+"+$";
return str.matches(patStr);
}
4、SQL语句处理:
查询SQL中需要使用 escape 关键字声明使用了哪字符作为转义字符,以oracle数据库使用 "" 作为转义字符为例;在查询条件后面 增加 escape '' 语句就可以了
<if test="record.name != null and record.name != '' and (record.name.contains('%'.toString()) or record.name.contains('_'.toString())) ">
and c.name like CONCAT(CONCAT('%',#{record.name,jdbcType=VARCHAR}),'%') escape '\'
</if>
<if test="record.name != null and record.name != '' and !(record.name.contains('%'.toString()) or record.name.contains('_'.toString())) ">
and c.name like CONCAT(CONCAT('%',#{record.name,jdbcType=VARCHAR}),'%')
</if>
5、针对不同数据库的说明:
以Oracle和MySQL为例(其他数据库类似): Oracle中没有默认的转义字符,所以查询条件中都需要使用 escape 关键字声明使用了什么字符作为转义字符, 例如:
SELECT * FROM CONTRACT WHERE NAME LIKE '%\%%' escape '\' ;
MySQL中已经设置了默认的转义字符“\”,因此可以直接使用 “\”进行转义,不需要再进行声明,相反这个时候再重复声明会报错。 使用 escape 可以声明其他字符作为转义符号 例如:
SELECT * FROM CONTRACT WHERE NAME LIKE '%@%%' escape '@' ;