天天看點

oracle 遊标 上限,ORA-01000: 超出打開遊标的最大數

語言:java,資料庫:oracle

開發中通過jdbc做批量删除對象時,出現了如下異常:

java.sql.SQLException: ORA-01000: 超出打開遊标的最大數

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)

at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)

at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)

出現這種異常的原因很明确:超出打開遊标的最大數。

分析:

Java代碼中,執行conn.createStatement()或conn.prepareStatement()建立statement時,相當于在資料庫中打開了一個cursor。是以,如果你的createStatement和prepareStatement是在一個循環裡面的話,就會非常容易出現這個問題,因為遊标在不停的打開卻沒有關閉。

解決這個問題的方法有兩種:

修改資料庫遊标cursor上限值

oracle 遊标 上限,ORA-01000: 超出打開遊标的最大數

從上圖中可以看出oracle目前資料庫的遊标cursor上限值是300,我們需要修改它的值,如下圖所示将cursor值修改為最大值1000

oracle 遊标 上限,ORA-01000: 超出打開遊标的最大數

從上圖可以看出oracle的遊标值已經被修改為1000了。

但是仔細思考就可以看出這種方法是治标不治本的,如果代碼的循環次數增多,依然會出現目前這個異常,是以最根本的解決方法是重構代碼。

重構java代碼

未重構前的代碼片段:

for (long i = 0; i <= 10000; i++) {

String sql = "insert into telepnum values(" + i + ")";

stmt = con.createStatement(); // 這裡是問題的所在

stmt.executeUpdate(sql);

}

重構後的代碼片段:

for (long i = 0; i <= 10000; i++) {

String sql = "insert into telepnum values(" + i + ")";

stmt = con.createStatement(); // 這裡是問題的所在

stmt.executeUpdate(sql);

stmt.close(); //及時關閉statement

}

更好的解決方案是将con.createStatement()語句放到循環的外面,一勞永逸。

con = insert.getConnection();

stmt = con.createStatement(); // 移動到這裡,Statemet是可以重用的

for (long c = a; c <= b; c++) {

String sql = "insert into telepnum values(" + c + ")";

stmt.executeUpdate(sql);

}

stmt.close(); //及時關閉statement

而且,絕大部分情況下,open_cursors隻需要設定一個比較小的值,就足夠使用了,除非有非常特别的要求。