轉載請注明出處:http://www.cnblogs.com/xunzhaorendaxia/p/8570604.html
解決方案將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; }
//kmp特征向量 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; } //KMP算法 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( ?))