fixed Oracle SQL報錯 #ORA-01460: 轉換請求無法實施或不合理
阿新 • • 發佈:2019-01-14
最近遇到一個oracle錯誤,之前並沒有遇到過,並不是select in超過1000個導致的,通過網上資料說是oracle版本導致,也有的說是oracle SQL過長導致。
然後通過自己實踐應該說是oracle SQL過長導致,看了一下SQL並不是很長,主要還是select in,因為主鍵換成uuid之後,來幾百個uuid的資料,select in就導致SQL過長報錯,我覺得網上所說的換oracle版本,也有可能是oracle版本對SQL過長支援不同。不過我還是通過改寫業務SQL解決問題的。專案中也不可能隨便就換oracle版本。
原來的程式碼,主要是select in 然後itemCode就是用;分隔的一大串的主鍵字串,然後又換成uuid的了,所以導致sql過長
/** * 獲取資訊模板 * @return */ private List<ApprSmsItemSettingVo> getSettingTemplate(String itemCode) throws SQLException { PreparedStatement pst = null; StringBuffer sb = new StringBuffer(); sb.append("select a.itemCode, "); sb.append("a.type, "); sb.append("b.warn_days, "); sb.append("c.proj_name, "); sb.append("c.cust_name, "); sb.append("a.is_send "); sb.append("from t_item_setting a "); sb.append("left join t_itm_define b on b.itemCode= a.itemCode "); sb.append("b.itemCode where a.is_send in (1) and a.itemCode in (?) "); pst = this.connection.prepareStatement(sb.toString()); pst.setString(1, itemCode); ResultSet rs = pst.executeQuery(); List<ItemSettingVo> list = new ArrayList<ItemSettingVo>(); while(rs.next()){ ItemSettingVo vo = new ItemSettingVo(); vo.setItemCode(rs.getString("itemCode")); vo.setType(rs.getLong("type")); vo.setSmsTemplet(rs.getString("sms_templet")); vo.setWarnDays(rs.getLong("warn_days")); vo.setIsSend(rs.getLong("is_send")); list.add(vo); } rs.close(); pst.close(); return list; }
解決方法:用分組遍歷再拼裝為一個List的方法,這樣就可以避免select in,然後in裡面又是一大堆uuid的資料,然後就導致sql執行過長報錯了
/** * 獲取資訊模板 * fixed #ORA-01460: 轉換請求無法實施或不合理 * ps:主鍵換成uuid之後,原來的方法會出現ORA-01460出錯,sql太長導致 * @param itemCode * @return * @throws Exception */ public List<ItemSettingVo> getItemSettingVos(String itemCode)throws Exception{ List<ItemSettingVo> templateList = new ArrayList<ItemSettingVo>(); StringBuffer itmStr = new StringBuffer(); //XXX fixed Exception#ORA-01460: 轉換請求無法實施或不合理 modify on 20190109 //暫時用分組遍歷再拼裝為一個List的方法,原來的方法放在getSettingTemplate if(StringUtils.isNotBlank(itemCode)){ //itemCode = itemCode.replace("(", "").replace(")", ""); String[] itemCodeArr = StringUtils.split(itemCode,","); int len = itemCodeArr.length; if (len < 100) {//沒超過100個事項編碼的情況,按照原來的方法 templateList = this.getSettingTemplate(itemCode); } else {//超過100個事項編碼的情況,分組遍歷,然後再拼裝list,避免Exception#ORA-01460: 轉換請求無法實施或不合理 List<Collection<String>> itms =CollectionUtils.splitCollection(Arrays.asList(itemCodeArr), 100); for (Collection<String> colle: itms) { for (String str : colle) { itmStr.append("'").append(str).append("'").append(","); } itemCode = itmStr.toString().substring(0, itmStr.toString().length()-1); templateList.addAll(this.getSmsSettingTemplate(itemCode)); itmStr.delete(0, itmStr.length()); } System.out.println("get apprTemplateList:{}"+templateList.size()); } } return templateList; }
集合拆分工具類,工具類複製公司同事寫的程式碼
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class CollectionUtils {
public static List<Collection<String>> splitCollection(Collection<String>values , int size) {
List<Collection<String>> result = new ArrayList<Collection<String>>();
if(values.size() <= size ){
result.add(values);
}else{
int count =0;
Collection<String> subCollection= null;
for(String s:c){
if(subCollection == null){
subColletion = new ArrayList<String>();
result.add(subColletion);
}
subCollection.add(s);
count++;
if(count == size){
count =0;
subCollectiion = null;
}
}
}
}
}