java用字符串拼接SQL语句的特殊字符转义问题

在实际的项目开发中,往往会根据用户在界面的文本框中输入的信息,去数据库中做模糊查询。如果使用的是原始的JDBC和SQL,往往需要对用户的输入进行转义,避免生成的sql语法错误,或者防止SQL注入。比如对输入的%和_和‘,就需要进行转义,因为这3个字符是SQL的特殊字符,如果不处理会导致sql出错或者是查询数据不正确。

假如有这样1个查询请求,模糊查询标题中包含a%b_cc‘d的记录,正确的sql应该是下面这样的:

select * from t_sch_work_info t where  t.title like  '%a/%b/_cc''d%' ESCAPE '/';

这就需要对String content = "a%b_cc‘d";进行转义后,再拼成SQL语句。oracle数据库允许我们使用自己定义的字符作为转义字符。看了下我们项目DAO层的编码风格,使用到了2种转义字符 \  和  /  。定位问题的时候发现,有人拼接SQL语句出错。自己用这2种字符,写了2个公用方法,经过测试是正确的。

/**
     *
     * 对content的内容进行转换后,在作为oracle查询的条件字段值。使用/作为oracle的转义字符,比较合适。<br>
     * 既能达到效果,而且java代码相对容易理解,建议这种使用方式<br>
     * "%'" + content + "'%  ESCAPE '/' "这种拼接sql看起来也容易理解<br>
     *
     * @param content
     * @return
     */
    public static String decodeSpecialCharsWhenLikeUseBackslash(String content)
    {
        // 单引号是oracle字符串的边界,oralce中用2个单引号代表1个单引号
        String afterDecode = content.replaceAll("'", "''");
        // 由于使用了/作为ESCAPE的转义特殊字符,所以需要对该字符进行转义
        // 这里的作用是将"a/a"转成"a//a"
        afterDecode = afterDecode.replaceAll("/", "//");
        // 使用转义字符 /,对oracle特殊字符% 进行转义,只作为普通查询字符,不是模糊匹配
        afterDecode = afterDecode.replaceAll("%", "/%");
        // 使用转义字符 /,对oracle特殊字符_ 进行转义,只作为普通查询字符,不是模糊匹配
        afterDecode = afterDecode.replaceAll("_", "/_");
        return afterDecode;
    }

 /**
     * 对content的内容进行转换后,在作为oracle查询的条件字段值。使用\作为oracle的转义字符。<br>
     * 这种做法也能达到目的,但不是好的做法,比较容易出错,而且代码很那看懂。<br>
     * "%'" + content + "'%  ESCAPE '\' "这种拼接sql实际上是错误的.<br>
     * "%'" + content + "'%  ESCAPE '\\' "这种拼接sql才是正确的<br>
     *
     * @param content
     * @return
     */
    public static String decodeSpecialCharsWhenLikeUseSlash(String content)
    {
        // 单引号是oracle字符串的边界,oralce中用2个单引号代表1个单引号
        String afterDecode = content.replaceAll("'", "''");
        // 由于使用了\作为ESCAPE的转义特殊字符,所以需要对该字符进行转义
        // 由于\在java和正则表达式中都是特殊字符,需要进行特殊处理
        // 这里的作用是将"a\a"转成"a\\a"
        afterDecode = afterDecode.replaceAll("\\\\", "\\\\\\\\");
        // 使用转义字符 \,对oracle特殊字符% 进行转义,只作为普通查询字符,不是模糊匹配
        afterDecode = afterDecode.replaceAll("%", "\\\\%");
        // 使用转义字符 \,对oracle特殊字符_ 进行转义,只作为普通查询字符,不是模糊匹配
        afterDecode = afterDecode.replaceAll("_", "\\\\_");
        return afterDecode;
    } 

对比上面的代码,很容易看出使用/,代码更简单,更容易理解。之所以写这个博客,不是推荐大家去手动拼接SQL字符串,因为这种做法效率很低,而且很容易出错。实际开发中,我们应该使用JDBC或者hibernate等框架,提供的预编译SQL。使用预编译语句不仅让代码可读性更好,而且还会有性能优势。可以参考这篇文章:

HQL或SQL使用?带来的好处:减少SQL解析时间、降低内存开销、防止SQL注入

时间: 2024-10-25 03:13:16

java用字符串拼接SQL语句的特殊字符转义问题的相关文章

Java中如何拼接sql或者其他含有变量语句

个人浅谈Java拼接sql语句原则. 本原则是个人感悟(不保证完全正确) 第一条原则,首先将一条完整的字符串写好.(例如是"select * from users where id=(id+1)") 凡是变量都需要在其前面加上+,且前面是要加上",如果后面不是",则后面必须也要加上+". 第二条原则如果遇上括号(id+1),那加号必定死以括号为原则的,在(号之前加上+,并且前方是",而且后方也是+" 第三条原则,如果后期遇到的是变量后面

SQLSERVER 根据传入的参数拼接sql语句字符串,反馈结果集

ALTER PROCEDURE [dbo].[usp_visit_detail](@siteid BIGINT, @Startime VARCHAR(15), @Endtime  VARCHAR(15), @Aflag  INT = 10,                                    --初始值为10,非10,则表示有传入参数 @Area   VARCHAR(20) = 'N',               -- --初始值为N,非N,则表示有传入参数 @Nflag  

java动态拼接sql语句并且执行时给sql语句的参数赋值

问题 在这里举一个例子,比如我要做一个多条件模糊查询,用户输入的时候有可能输入一个条件,也有可能输入两个条件,这时执行查询的sql语句就不确定了,但可以用动态拼接sql语句来解决这个问题. 解决方法 1.就拿我上面的那个多条件模糊查询为例,第一步是拼接sql语句,先定义一个通用的sql语句,String sql = "select * from user where 1 = 1 ";这里添加where 1= 1是一个小技巧,方便后面sql语句的拼接. String sql = &quo

使用表达式避免拼接SQL语句

在SQL语句编写过程中,无论在存储过程中还是在程序中,有时为了使语句兼容全部情况与某字段的特殊情况,不得不拼接SQL字串 如下表 商品ID 类别ID 1 1 2 1 3 2 4 3 5 3 如果我们要写一个SQL,改SQL可通过类别ID获得该类别的商品ID,并且要求兼容传入类别ID为0时获得所有商品,我们不得不拼接SQL了 --@类别ID为传入的参数 DECLARE @Sql NVARCHAR(500) SET @Sql='SELECT * FROM 商品' IF(@类别ID!=0) SET @

sqlserver 存储过程中拼接sql语句 动态执行

ALTER PROC [dbo].[Student_Friend_Get] @startRowIndexId INT, @maxNumberRows INT, @schoolId INT, @gradeId INT, @cId INT, @keyWords NVARCHAR(100), @userName VARCHAR(50) AS BEGIN DECLARE @sqlfilter VARCHAR(max) SET @sqlfilter = ' ' IF(@schoolId <> -1) S

java反射获取注解并拼接sql语句

先建两个注解 分别为 Table 和 Column package com.hk.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(Ret

SqlServer和Oracle从多行记录(数据集)中查询结果并拼接成一个字符串的SQL语句(纵表数据转成拼接的文本)

使用情景: 例如:需要从学生成绩表中,查询分数大于95分的所有学生编号,用逗号分隔成一个字符串. 准备测试数据: create table score (id int,score int) insert into score values(1,90) insert into score values(2,96) insert into score values(3,99) 现在需要通过一个语句查询重"2,,3"这个结果字符串. SQL Server语句如下: select substr

动态拼接SQL语句

1.参考官方文档 ? if:字符判断 ? choose (when, otherwise):分支选择 ? trim (where, set):字符串截取:其中where标签封装查询条件,set标签封装修改条件 ? foreach 2.if案例 1)在EmployeeMapper接口中添加一个方法: //携带了哪个字段,查询条件就带上哪个字段的值 public List<Employee> getEmployeeByConditionIf(Employee employee); 2).如果要写下

关于拼接SQL语句sqlMap的使用方法

1.为什么使用? 主要还是为了代码中获取到值,然后带入SQL语句中拼接查询 2.怎么使用? 1)bean继承了BaseEntity类,该类中有 /** * 自定义SQL(SQL标识,SQL内容) */ protected Map<String, String> sqlMap; @JsonIgnore @XmlTransient public Map<String, String> getSqlMap() { if (sqlMap == null){ sqlMap = Maps.ne