Erreur ORA-1000 ouverte dans la session Oracle Database Cette erreur se produit lorsque le nombre de curseurs dépasse la valeur maximale.
ORA-1000 Le nombre maximum de curseurs ouverts a été dépassé.
Essayons-le immédiatement. 彡 (゜) (゜) Commencez par préparer la table.
CREATE TABLE TBL_A(
C1 NUMBER
, C2 VARCHAR2(30)
);
En SQL, qui est une variable de liaison de PreparedStatement, La source est écrite de manière à ce que les astuces et les erreurs ORA-1000 se produisent.
Il existe une méthode prepareStatement dans la boucle for, et le curseur est déplacé à chaque fois. Il sera nouvellement ouvert et une erreur se produira. 彡 (゚) (゚)
C'est plein de putains d'éléments de code, mais si je saute Masakari (Akan 彡 (-) (-)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) throws Exception {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
int i;
Connection conn = null;
PreparedStatement ps = null;
System.out.println(new Date() + " Connect...");
try {
//DB Connect
conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
//Close
conn.close();
} catch(SQLException ex) {
conn.rollback();
ex.printStackTrace();
System.exit(1);
} finally {
if (ps != null) { ps.close(); }
if (conn != null) { conn.close(); }
}
//End
System.out.println(new Date() + " End...");
}
}
Lorsqu'elle est exécutée, l'erreur ORA-1000 suivante se produit. 彡 (゚) (゚)
$ javac ./InsertTest.java
$ java -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar InsertTest
Thu Nov 30 00:57:01 JST 2017 Connect...
Thu Nov 30 00:57:23 JST 2017 Insert...
java.sql.SQLException: ORA-01000: maximum open cursors exceeded
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:446)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1054)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:623)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:59)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:910)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1119)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3780)
at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1343)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3887)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1079)
at InsertTest.main(InsertTest.java:27)
Caused by: Error : 1000, Position : 0, Sql = INSERT INTO TBL_A (C1, C2) VALUES (:1 , :2 ), OriginalSql = INSERT INTO TBL_A (C1, C2) VALUES (?, ?), Error Msg = ORA-01000: maximum open cursors exceeded
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:498)
... 14 more
$ echo $?
1
Si vous mettez le prepareStatement en dehors de la boucle for Vous pouvez éviter l'erreur ORA-1000. Est-ce vrai? 彡 (゜) (゜)
:
//Insert Execute
System.out.println(new Date() + " Insert...");
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
:
Vérification nulle de l'objet et du premier prepareStatement Si vous le faites, vous pouvez éviter l'erreur ORA-1000.
:
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
if (ps == null) {
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
}
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
:
Ce sera une variante de la solution de contournement 1. 彡 (゚) (゚) Si vous adoptez la syntaxe try-with-resources que vous avez enseignée dans l'article précédent, Éviter la première écriture anti-pattern "naturellement" L'erreur ORA-1000 ne se produit pas. Le point est "naturellement".
La source est propre et toutes les bonnes choses sont 彡 (゚) (゚)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
//try-with-resources Statement
System.out.println(new Date() + " Connect...");
try (
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
) {
//Initialize
int i;
//AutoCommit Setting
conn.setAutoCommit(false);
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
Objet PreparedStatement dans une boucle Vous pouvez éviter l'erreur ORA-1000 en fermant () à chaque fois.
:
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
ps.close();
}
//Commit
conn.commit();
:
Est-ce difficile d'analyser chaque fois que j'écris de cette façon? J'ai pensé, L'analyse dure peut être évitée à chaque fois avec la fonction de cache d'instructions
À propos du cache d'instructions https://docs.oracle.com/cd/E16338_01/java.112/b56281/stmtcach.htm#i1069942 : -Evite les analyses répétées et la création de phrases. :
Une autre personne a demandé: "La portée des variables dans l'anti-modèle n'est-elle pas étrange en premier lieu?" On m'a fait remarquer, donc si je modifie la source pour déclarer la variable dans la clause try ... Eh bien, cela devient naturellement un code de type 1. solution de contournement. La syntaxe try-with-resources est importante, n'est-ce pas? (゜) (゜)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
System.out.println(new Date() + " Connect...");
try {
//Init
int i;
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
//Close
ps.close();
conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
J'ai reçu un commentaire sur addBatch dans les commentaires, je l'ai donc modifié en fonction de la source supplémentaire. Je me demande si ça va comme ça ... 彡 (゚) (゚) Le manuel pour addBatch (mise à jour par lots) est [ici](https://docs.oracle.com/cd/F19136_01/jjdbc/performance-extensions.html#GUID -FEECA64F-44F4-453F-B8A8-AFBF6D29ABA4)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
System.out.println(new Date() + " Connect...");
try {
//Init
int i;
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.addBatch();
}
//Execute(batch updates)
int[] updateCounts = ps.executeBatch();
System.out.println(new Date() + " Batch Counts..." + updateCounts.length);
//Commit
conn.commit();
//Close
ps.close();
conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
$ javac ./InsertTest.java
$ java -classpath .:/u01/app/oracle/product/version/db_1/jdbc/lib/ojdbc8.jar InsertTest
Tue Aug 20 04:18:11 EDT 2019 Connect...
Tue Aug 20 04:18:13 EDT 2019 Insert...
Tue Aug 20 04:18:14 EDT 2019 Batch Counts...2000
Tue Aug 20 04:18:14 EDT 2019 End...
$
Recommended Posts