去除SQL语句某查询条件

摘要:
[CDATA[${SQL}]]˃因为我传递的是SQL语句而不是特定条件,所以当SQL语句中出现比较字符等特殊字符时,XML将帮助我转义。我不需要XML来逃避SQL,所以我使用包装SQL语句,使SQL语句不会被转义。现在背景清楚了。如果我想完成这些需求,我必须在SQL进入XML映射文件之前处理一些条件。看看removeSQL方法:/***从SQL语句中删除查询条件*@paramsql*@paramchoice*@return*/publicstaticStringremoveSQL{intcho_first=SQL.indexOf;intbefore_and=SQL.lastIndexOf;int before_where=SQL.llastIndexOf;intafter_and=SQL.indexOf;intaftr_where=SQL.inindexOf;if(before_wwhere!

去除SQL语句某查询条件第1张

工作需求:根据不同条件查询数据,目前有下拉列表和单选按钮两种

去除SQL语句某查询条件第2张

如果只是查询具体的条件,那很简单,只需要在where 条件之后加上相应的条件即可,像这样:where type = ‘门诊’。当查询的是全选或全部时,显然的就要把相应的条件给去除,如果你是使用mybatis,那也很简单,只需要在xml映射文件里加上一些判断条件,像这样:

<select   parameterType="user" resultType="User">select *from user
          <where>
            <if test="id!=null and id!=''">id=#{id}
            </if>
            <if test="type!=null and type!=''">and type=#{type}
            </if>
            <if test="gender!=null and gender!=''">and gender=#{gender}
            </if>
          </where>
       </select>

但是项目中的需求往往千奇百怪,由于我的SQL语句是写在json配置文件里的,而我又使用的是mybatis框架,我没办法将SQL语句直接写在mybatis的xml映射文件里,我只有把SQL作为一个参数传递给映射文件,就像上面传递id,type,gender一样。

<select   parameterType="java.lang.String" resultType="Map">
        <![CDATA[ ${SQL} ]]> 
    </select>

因为我传递的是一句SQL语句而不是具体条件,当我的SQL语句里出现特殊字符如比较字符时XML是会帮我转义的,我不需要XML去转义我的SQL,所以我要使用

 <![CDATA[  ]]> 

将我的SQL语句包裹起来,这样SQL语句就不会被转义了。这里使用${ SQL }而不是#{ SQL },#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,$将传入的数据直接显示生成在sql中,显然我的SQL语句不需要加双引号。(这里我也先不考虑使用$会导致SQL注入的问题,后期我也会去做SQL检查)

现在背景已经明确,如果想完成需求,我只有在SQL进入XML映射文件之前,将一些条件处理掉。SQL是写在json配置文件里的,预先的条件也是写死的,如下:

"sql":"SELECT nvl(sum(a.ssrc),0) as count FROM CB_ME_YLZL a,CB_DI_DATE b,CB_DI_YLJG c,CB_DI_JZLX d WHERE a.sjid=b.sjid and a.yljgid=c.yljgid and a.jzlxid=d.jzlxid and c.yljgdj='3' and c.yljgmc = #{select1_val_select}  AND type = #{radio1_val_radio}"

当用户选择全选或是全部时,我需要把

and c.yljgmc = #{select1_val_select}  AND type = #{radio1_val_radio}

去掉。不是全选或全部时我需要把

#{select1_val_select}   #{radio1_val_radio}

替换成相应的条件。

代码如下:

/*** 处理SQL语句
     * 
     * @paramsql
     * @return
     */
    public staticString dealSQL(String sql, String str) {
        sql = sql.trim().toUpperCase().replaceAll(" +", " ");
        int form = sql.indexOf(" FROM ");
        String begin = sql.substring(0, form);
        begin = begin.replaceAll(" AS ", " AS C_");
        String end =sql.substring(form, sql.length());
        sql = begin+end;
        String[] split1 = str.trim().toUpperCase().replaceAll("'", "").replaceAll(""", "").split(",");
        for(String s : split1) {
            if(StringUtils.isNotBlank(s)) {
                String[] split2 = s.split(":");
                
                if(sql.contains(split2[0])) {
                    if(split2[0].contains("VAL_RADIO") || split2[0].contains("VAL_SELECT")) {
                            if(split2[1].equals("全选") || split2[1].equals("全部")) {
                                sql = removeSQL(sql,"#{"+split2[0]+"}");
                            }else{
                                sql = sql.replace("#{"+split2[0]+"}", "'" + split2[1] + "'");
                            }
                    }else{
                        sql = sql.replace("#{"+split2[0]+"}", "'" + split2[1] + "'");
                    }
                }
            }
        }
        returnsql;
    }

json配置文件里规定需要展现的字段都要使用as ** 作为别名,但是如果别名为数字或特殊字符的话,oracle是不认的,如果别名使用双引号引起来,orace认但json文件又不认了,所以我使用最low的办法,将所有别名加上一个C_,这样数据库就认了。

看一下removeSQL方法:

/*** 去除SQL语句某查询条件
     * @paramsql
     * @paramchoice
     * @return
     */
    public staticString removeSQL(String sql,String choice) {
        int cho_first =sql.indexOf(choice);
        int before_and = sql.lastIndexOf(" AND ", cho_first);
        int before_where = sql.lastIndexOf(" WHERE ", cho_first);
        int after_and = sql.indexOf(" AND ", cho_first);
        int after_where = sql.indexOf(" WHERE ",cho_first);
        
        if(before_where != -1) {
            if(before_and != -1) {
                if(before_and >before_where) {
                    sql = sql.replace(sql.substring(before_and, cho_first), " ").replace(choice, " ");
                }else{
                    if(after_and != -1) {
                        if(after_where != -1) {
                            if(after_and <after_where) {
                                sql = sql.replace(sql.substring(before_where+7, after_and+5), " ");
                            }else{
                                sql = sql.replace(sql.substring(before_where, cho_first), " ").replace(choice, " ");
                            }
                        }else{
                            sql = sql.replace(sql.substring(before_where+7, after_and+5), " ");
                        }
                    }else{
                        sql = sql.replace(sql.substring(before_where, cho_first), " ").replace(choice, " ");
                    }
                }
            }else{
                if(after_and != -1) {
                    if(after_where != -1) {
                        if(after_and <after_where) {
                            sql = sql.replace(sql.substring(before_where+7, after_and+5), " ");
                        }else{
                            sql = sql.replace(sql.substring(before_where, cho_first), " ").replace(choice, " ");
                        }
                    }else{
                        sql = sql.replace(sql.substring(before_where+7, after_and+5), " ");
                    }
                }else{
                    sql = sql.replace(sql.substring(before_where, cho_first), " ").replace(choice, " ");
                }
            }
        }
        
        int cho =sql.indexOf(choice);
        if(cho != -1) {
            returnremoveSQL(sql,choice);
        }else{
            returnsql;
        }
    }

逻辑也就是:当条件在不同地方,处理方式不同而已,下面是几种罗列的可能存在条件的地方,上面代码就是针对这些不同地方,将这些条件连同其前的and或者where(不影响其后的and条件使用的where,如下图第二条语句第一处位置的条件)去掉。(针对复杂的SQL,如使用with as 将查询数据做临时表,之后再使用select查询临时表的,这些代码是不能处理的)

去除SQL语句某查询条件第3张

去除SQL语句某查询条件第4张

免责声明:文章转载自《去除SQL语句某查询条件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis限流的实现方式有3种安卓音频采集播放方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

RAC实例 表空间 维护

先配置一下监听,这样我们就可以从客户端进行连接了。 我这里写了三种连接。 第一种是正常方式,一般都采用这种方式,后面的rac1和rac2 是方便测试。因为如果用第一种方式的话,客户端连哪个实例是随机的,不好进行控制,除非手动的关闭某个实例,让Oracle 漂过去,那样有点麻烦。 我就又多添加了2个监听,分别对应实例1和实例2.  配置这2个监听的时候,要注...

Hive 时间函数

--Hive中日期函数总结: --1.时间戳函数 --日期转时间戳:从1970-01-01 00:00:00 UTC到指定时间的秒数 select unix_timestamp(); --获得当前时区的UNIX时间戳 select unix_timestamp('2017-09-15 14:23:00');  select unix_timestamp('...

Oracle SQL外连接

SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。连接类型        定义内连接           只连接匹配的行左外连接        包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行右外连接        包含右边表的全部行(不管左边的表中是否存在...

access数据库删除两个日期之间 的数据 SQL语句

sql2005中sql语句为 DELETE FROM table WHERE ([date] BETWEEN '2011 - 9 - 19 0 : 00 : 00 ' AND '2011 - 9 - 20 0 : 00 : 00') 词语法是正确的,发现再access中没有影响相关行数,解决方法在日期前后加上#,语法为: delete from table...

HTML、jsp页面中radio,checkbox,select数据回显功能,默认被选中问题

最近常常遇到各种复选框、单选框、下拉框的默认被选中的问题,开始也是绞尽脑汁的想办法,今天写一篇学习总结的博文来写一下学习总结。 单选框(radio)默认被选中: 一、jstl技术进行回显 <input type="radio" name="sex" <f:if test="${c.sex=='男' }">checked="checked"...

游标(cursor)--显式游标&amp;amp;隐式游标、游标四个属性、循环遍历

https://blog.csdn.net/qq_36743482/article/details/79354036 1.1 cursor是什么cursor是光标,游标的意思。比如我们的鼠标的光标就是cursor。那么在数据库中cursor是什么呢?当运行DML(select,update,insert,delete)语句时,ORACLE会在内存中为其分配...