解决SQL in 1000条限制
2015-06-16 00:00
363 查看
处理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(); // 获得一共有多少类
这里探讨得是另一种实现方式,将传入的项在数据库做类似于虚拟表的一列数据,然后做关联查询。
数据库创建函数和类型:
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(); // 获得一共有多少类
相关文章推荐
- Oracle11g闪回技术
- Windows 2008 双机群集配置(for SQLServer)
- 如何设计数据库(2)
- 如何设计数据库(1)
- Memcache环境搭建_me
- MYSQL
- MySQL-分区表-2
- oracle 数据导入导出 之expdp impdp
- mysql SELECT FOUND_ROWS()与COUNT(*)用法区别
- oracle中表的操作
- [转载] nosql 数据库的分布式算法
- oracle创建表空间
- mysql的root密码丢失解决方案
- MySQL优化GROUP BY-松散索引扫描与紧凑索引扫描
- MySQL如何利用索引优化ORDER BY排序语句
- oracle中表的锁定
- 数据库事务
- 【Oracle篇】Oracle初试水
- Redis 一致性hash
- C# MySQL DataAdapter