近日做一个短信平台的项目,需要将几十万的数据插入到Oracle数据库中,下面的代码在一百条数据下是正确执行的,但五百条的时候就报错。所报的错误为“java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01000: 超出打开游标的最大数”,求大侠指教
- Java code
try { conn = getDba().getConnection(); conn.setAutoCommit(false); for (TblMmsImpPhone importNum:numList) { String sql = "insert into tbl_mms_importphone (id,phonenum,flag,temid) values(SEQ_TBL_IMPORTPHONE.nextval,'"+ importNum.getPhonenum()+ "',0,"+ importNum.getTemId() + ")"; ps = conn.prepareStatement(sql); count += ps.executeUpdate(); if ((count % 100) == 0) { conn.commit(); } } conn.commit();conn.setAutoCommit(true);} catch (Exception e) { success = false; try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace();} finally { close(ps, conn);}
------解决方案--------------------------------------------------------
ORA-00604: 递归 SQL 级别 1 出现错误,ORA-01000: 超出打开游标的最大数
这两个错误一般出现在利用代码循环执行数据库命令(例如将数据导入到数据库)时,例如在C#中
1)建立一个OracleConnection
2)循环创建OracleCommand,并执行数据导入
3)关闭OracleConnection
当第二步的循环数比较小时,代码运行正常。当循环数超过一定值(例如300),代码就会出错。提示:
ORA-01000: 超出打开游标的最大数
这是因为Oracle数据库中打开的游标最大数为一定值,例如300,当代码中第二步时, 循环中一个Command占用了一个数据库游标,执行的循环超过这个数时就会产生游标数目溢出错误。
解决办法:
第二步循环中中每次执行完OracleCommand,都将command.dispose()下,释放掉这个资源就好了
此外,也可以修改数据库的最大游标数,不过这个方法治标不治本。
------解决方案--------------------------------------------------------
首先把insert语句改成insert into tbl_mms_importphone (id,phonenum,flag,temid) values(?,?,?,?)的形式,这样可以减少sql编译的时间。
其次改成batch update的方式
ps = conn.prepareStatement(sql);
ps.addBatch();
判断batch数目然后ps.executeBatch();
------解决方案--------------------------------------------------------
这个我好像遇到过一次,和ORACLE的配置有关系,因为你用的是一个连接提交大量数据在oracle中要重新配置,修改oracle中的配置。
prepareStatement没必要吧,这个是处理带占位符的,你也没用啊?
还有你用的是连接池吧?
你采用3楼的方式:改成batch update的方式。应该没问题,最好还是做手动提交,自动提交会有不可预知的事