处理oracle sql 语句in子句中(where id in (1, 2, ..., 1000, 1001)),如果子句中超过1000项就会报错。这主要是oracle考虑性能问题做的限制。如果要解决次问题,可以用 where id (1, 2, ..., 1000) or id (1001, ...)。
这里探讨得是另一种实现方式,将传入的项在数据库做类似于虚拟表的一列数据,然后做关联查询。
数据库创建函数和类型:
CREATE OR REPLACE TYPE mytable AS TABLE OF varchar2(5000);
CREATE OR REPLACE FUNCTION STR_SPLIT (src clob, delimiter varchar2)
RETURN mytable IS
psrc clob;
a mytable := mytable();
i NUMBER := 1;
j NUMBER := 1;
BEGIN
psrc := RTrim(LTrim(src, delimiter), delimiter);
LOOP
i := InStr(psrc, delimiter, j);
IF i>0 THEN
a.extend;
a(a.Count) := Trim(SubStr(psrc, j, i-j));
j := i+1;
END IF;
EXIT WHEN i=0;
END LOOP;
IF j <= Length(psrc) THEN
a.extend;
a(a.Count) := Trim(SubStr(psrc, j, Length(psrc)+1-j));
END IF;
RETURN a;
END;
函数STR_SPLIT 主要是将传入的参数src项,根据delimiter 分隔符分割成表的一列数据。src类型为clob主要考虑传入字符串超过4000的限制。
java调用:
service层:
boolean pand = true; //字符串 元素个数是否小于1000
if(StringUtil.isNotBlank(userCode)) {
if (userCode.split(",").length > 1000)
pand = false;
if (pand) {
where += " and u.usercode not in ("+userCode+")";
} else { //传参
where += " and u.usercode not exists (select distinct column_value from table(CAST(SEND_SPLIT(?, ',') as mytable)) where u.usercode=column_value)";
}
}
//如果大于1000 非包含用not exists比not in效率高。
// in/not in (select distinct column_value from table(CAST(SEND_SPLIT(?, ',') as mytable)
// exists/ not exists (select distinct column_value from table(CAST(SEND_SPLIT(?, ',') as mytable) 主表.字段=column_value))
where += " order by u.username";
sql.append(where);
if (pand)
return mapDataDao.queryListBySQL(sql.toString());
else
return mapDataDao.queryListBySQLParam(sql.toString(), new Object[] {userCode});
dao层:
Connection conn = getConnection(jndiName, session);
ResultSet rs = null;
//OraclePreparedStatement statement = null;
PreparedStatement statement = null;
OracleConnection connection = null;
List list = new JSONArray();
PaginationSupport ps = null;
try {
//NewProxyConnection转换为OracleConnection
C3P0NativeJdbcExtractor cp30NativeJdbcExtractor = new C3P0NativeJdbcExtractor();
connection = (OracleConnection) cp30NativeJdbcExtractor.getNativeConnection(conn);
//statement = (OraclePreparedStatement)connection.prepareStatement(sql);
statement = conn.prepareStatement(sql);
if (param[0] != null && param[0].toString().length() > 0) {
//statement.setStringForClob(1, param[0].toString());
CLOB clob = CLOB.createTemporary(connection, false, oracle.sql.CLOB.DURATION_SESSION);
clob.open(CLOB.DURATION_SESSION);
Writer writer = clob.getCharacterOutputStream();
writer.write(param[0].toString().toCharArray());
writer.flush();
writer.close();
statement.setClob(1, clob);
}
rs = statement.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData(); // 获得结果集的模型(列的相关信息)
int columnCount = rsmd.getColumnCount(); // 获得一共有多少类