解决方案将select * from tablename where field in(arg1,arg2…arg1001)拆成select * from tablename where field in(arg1,arg2…arg1000) or field in(arg1001);

本案例代码为项目中处理SQL语句中<#in>标签代替in (?,?,?..)的情况;

public class FeildTest {
    public static void main(String[] args){
        String sql = "select * from id<#in>";
        int startSize = 21;
        System.out.println(ExtractFeild(sql,startSize));
    }

    private static String  ExtractFeild(String sql, int startSize) {
        
        String replaceTag = "<#in>";
        if(sql.contains(replaceTag)){
            String[] fields = sql.split(" ");
            String field = "";
            for (int i = 0; i < fields.length; i++) {
                String str = fields[i];
                if (str.contains(replaceTag)) {
                    if (str.equals(replaceTag)) {
                        field = fields[i-1];
                        break;
                    } else {
                        char[] fd = str.toCharArray();
                        char[] tags = replaceTag.toCharArray();
                        field = str.substring(0,KMP_Index(fd,tags));
                        break;
                    }
                }
            }
            StringBuffer sb = new StringBuffer("("+field+" in(");
            for (int i = 0; i < startSize/10; i++) {
                for (int j = 0; j < 10; j++) {
                    sb.append("?,");
                }
                sb.deleteCharAt(sb.length()-1);
                sb.append(")");
                if (startSize!=(i+1)*10) {
                    sb.append(" or ");
                    sb.append(field);
                    sb.append(" in( ");
                }
            }
            for (int i = 0; i < startSize%10; i++) {
                sb.append("?,");
            }
            sb.deleteCharAt(sb.length()-1);
            sb.append(")");
                        //额外的括号处理
            sb.append(")");
            
            //field<#in>之间空格兼容
            String regex = field+"\\s*"+replaceTag;
            sql = sql.replaceFirst(regex, sb.toString());
        }
        return sql;
    }
    
    private static int[] next(char[] t) {
        int[] next = new int[t.length];
        next[0]=-1;
        int i=0;
        int j=-1;
        while (i<t.length-1) {
            if (j==-1||t[i]==t[j]) {
                i++;
                j++;
                if (t[i]!=t[j]) {
                    next[i]=j;
                } else {
                    next[i]=next[j];
                }
            } else {
                j = next[j];
            }
        }
        return next;
    }

    private static int KMP_Index(char[] ss, char[] tt) {
        int[] next = next(tt);
        int i=0;
        int j=0;
        while ( i<=ss.length-1 && j<= tt.length -1) {
            if (j==-1||ss[i]==tt[j]) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
        if (j<tt.length) {
            return -1;
        } else {
            return i -tt.length;
        }
    }
}

其中用到了KMP算法来查找sql中该标签的位置,并作出处理计算出sql中<#in>标签个数;

其实算法逻辑结合网上资料很容易写出来;

不过在代码审查的过程中老大一眼就看出来个问题:

我原有SQL处理完想生成in (?,?,?,?..)or in (?,?,?..)这种结构

但是如果两边不加括号会存在逻辑上的错误;

比如我原计划select * from table where id in(1) or id in(2)and id=3;

是查不出来任何东西的;实际上会查出来select * from table where id in(1)的结果;这也是菜鸟程序员常见错误,

解决方案在处理此类SQL语句的时候多加()保证逻辑正确。

运行结果:

select * from (id in(?,?,?,?,?,?,?,?,?,?) or id in( ?,?,?,?,?,?,?,?,?,?) or id in( ?))

 

版权声明:本文为xunzhaorendaxia原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xunzhaorendaxia/p/8570604.html