Oracle数据库中in()参数超过一千报错代码报错
解决方案将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( ?))