java.sql.SQLException: ORA-01722: invalid number

Br4ve

Bekanntes Mitglied
Hallo,
ich habe ein Problem mit einem Prepared Statement von mir und zwar bekomme ich immer den fehler aus dem Titel, diesen hier:
Java:
java.sql.SQLException: ORA-01722: invalid number

	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
	at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:810)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
	at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:850)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1134)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3339)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3384)
	at datenbankZugriff.dbzugriff.anfragetest(dbzugriff.java:68)
	at tagHandler.test.main(test.java:16)

Der Code ist folgender:
Java:
public static ArrayList<Procstep> anfragetest(String pgid, String db){
	pgid = anfraPgids(pgid, db);
	pgid = pgid.substring(0, pgid.length()-2);
	
	System.out.println(pgid);
	ResultSet rs = null;
	PreparedStatement pstmt;
	Connection con = datenbankZugriff.dbverbindung.getConnection(db);
	ArrayList<Procstep> liste = new ArrayList<Procstep>();
	try {
		pstmt = con.prepareStatement("select process.name, processgroup.pgroupid,process.pid," +
				" processstep.seqnr, toolrelease.maincommand,processstep.status, " +
				"processstep.jobmachineid, processstep.psid, processinstance.pinid, " +
				"processstep.laststatuschange, processstep.priority, processinstance.startdate " +
				"from process,processgroup, processinstance,processstep,toolrelease where " +
				"process.pgroupid=processgroup.pgroupid and processgroup.pgroupid in (?) and " +
				"process.pid = processinstance.pid and processinstance.pinid = processstep.pinid " +
				"and processstep.treleaseid = toolrelease.treleaseid and process.name not like " +
				"'Admin %\' order by process.pid,processinstance.startdate ASC, " +
				"processstep.seqnr, processstep.psid");
		pstmt.setString(1, pgid);
		rs = pstmt.executeQuery();

Das statement ist relativ lang und deshalb wohl ziemlich unverständlich. Allerdings glaube ich auch nicht das man es verstehen muss. Ich setze hier beispielsweise foldenden String ein : pgid = "801, 614, 615, 616, 618, 619, 620, 802, 803, 804, 805, 806, 812, 813, 824, 843, 844, 869". Nun bekomme ich allerdings diesen Fehler, der meiner Recherche zufolge auftritt wenn man mit falschen Datentypen arbeitet bzw. filtern will. Das merkwürdige allerdings ist, dass wenn ich diesen String manuell einsetze direkt ins Statement, ohne die setString Methode, funktioniert es. ???:L
 
setString() wird natürlich einfache Anführungszeichen drumherum setzen,

soweit ich weiß, war kürzlich schon mal ein Thema, unterstützt PreparedStatement nichts hinsichlich Listen von Werten für IN-Abfragen,
baue also manuell zusammen, vielleicht durch eigene Methoden als quasi-Framework halbwegs gesichert,
oder wechsle auf höheres wie Hibernate, da geht das dann wieder,
(wobei ein String "801, 614, 615, 616, 618" dann auch nicht gerade die perfekte Vorgabe ist, schon auf List<Integer> zu parsen usw.)

edit:
java - PreparedStatement IN clause alternatives? - Stack Overflow
mit Link auf
JavaRanch Journal - October 2005 Volume 4 Issue 2
 
Zuletzt bearbeitet von einem Moderator:
muss nicht zwingend ein Problem sein, bei mir in Oracle ist das \ einfach ein \,
oder stört zumindest die Auswertung nicht gleich mit Fehlermeldung..

zum Escapen '' schreiben, zwei Hochkommata hintereinander
 
Also das habe ich als Problem bislang noch nicht festgestellt, bzw hat mich nicht gestört. Ich habe allerdings in diesem Zusammenhang einen weiteren Fehler, nachdem ich über Slater's Links eine dynamische Generierung der "?" und der entsprechenden setString-Methoden versucht habe zu realisieren.
Mein Code ist nun folgender:
Java:
public static ArrayList<Procstep> anfragetest(String pgid, String db){
	ArrayList<String> listepgid = new ArrayList<String>();
	listepgid = anfraPgids(pgid, db);
	String nuofpgid = "?";
	for(String s: listepgid){
	nuofpgid += " ?";
	}
	
	nuofpgid = nuofpgid.substring(0, nuofpgid.length()-2);
	ResultSet rs = null;
	PreparedStatement pstmt;
	Connection con = datenbankZugriff.dbverbindung.getConnection(db);
	ArrayList<Procstep> liste = new ArrayList<Procstep>();
	try {
		pstmt = con.prepareStatement("select process.name, processgroup.pgroupid,process.pid," +
				" processstep.seqnr, toolrelease.maincommand,processstep.status, " +
				"processstep.jobmachineid, processstep.psid, processinstance.pinid, " +
				"processstep.laststatuschange, processstep.priority, processinstance.startdate " +
				"from process,processgroup, processinstance,processstep,toolrelease where " +
				"process.pgroupid=processgroup.pgroupid and processgroup.pgroupid in ( " + nuofpgid + " ) and " +
				"process.pid = processinstance.pid and processinstance.pinid = processstep.pinid " +
				"and processstep.treleaseid = toolrelease.treleaseid and process.name not like " +
				"'Admin %\' order by process.pid,processinstance.startdate ASC, " +
				"processstep.seqnr, processstep.psid");
		int i = 1;
		for(String s: listepgid){
			pstmt.setString(i++, s);	
			
		}
		rs = pstmt.executeQuery();

jez bekomme ich wieder so eine schöne Oracle Fehlermeldung:

Java:
java.sql.SQLException: ORA-01745: invalid host/bind variable name

	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
	at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:810)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
	at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:850)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1134)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3339)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3384)
	at datenbankZugriff.dbzugriff.anfragetest(dbzugriff.java:77)
	at tagHandler.test.main(test.java:16)

Das bedeutet doch, dass ich bestimmte Variablennamen nicht benutzen darf. Und müsste meines Wissens "nuofpgid" betreffen. Allerdings verstehe ich nicht wieso das hier ein Problem ist.
 
immer noch setzt setString() Anführungszeichen, was nach deinem vorherigen erfolgreichen Test nicht anzuraten ist,
benutze setInteger/ setLong, was immer da ist, jedenfalls kein String,
die gegebenen Strings parsen, oder gleich bei Gewinnung umstellen

welchen Datentyp hat pgroupid?

dieses Vorgehen mit vielen ? finde ich nicht so toll, eine gewisse Sicherheit kann man aber wohl nicht absprechen,
beim Zusammenbau in der Schleife ist StringBuilder zu empfehlen,
aber das ist schon nur noch kleiner Performance-Tipp, andererseits ein wichtiger, lohnt sich durchaus zu lernen,

genauso allgemein zu verbessern:
Java:
ArrayList<String> listepgid = new ArrayList<String>();
listepgid = anfraPgids(pgid, db);
wird entweder zu
Java:
ArrayList<String> listepgid = null;
listepgid = anfraPgids(pgid, db);
oder
Java:
ArrayList<String> listepgid;
listepgid = anfraPgids(pgid, db);
oder gleich
Java:
ArrayList<String> listepgid = anfraPgids(pgid, db);
die erzeugte Liste bei dir wird jedenfalls gleich weggeworfen, ein neuer Rückgabewert in die Variable geschrieben,

List statt ArrayList als Typ der Variablen auch wieder empfehlenswert
 
Hm danke für deine Antwort ja eigentlich kann ich hier auch einfach Integer benutzen jetzt das dürfte kein Problem sein.
Wenn ich dich richtig verstehe, ist also diese Schreibweise die beste:
Java:
ArrayList<String> listepgid = anfraPgids(pgid, db);
Ist das so richtig? :rtfm:
Abschließend stellt sich mir dann noch die Frage wieso ist hier List ArrayList vorzuziehen? Was hat die List gegenüber der ArrayList für Vorteile?
 
der Rückgabewert von anfraPgids() sollte auch List sein, soweit wie überall vertretbar,
grundsätzlich könnte eine Methode dann die Liste wechseln, z.B. auf LinkedList, oder Datenbanken liefern oftmals komplizierte internere List-Klassen, die bei Zugriff erst noch einen Proxy initialisieren, Daten nachladen usw.,
bei diesem Wechsel wäre das Restprogramm unberührt, wenn gut programmiert

kurz: die Information ArrayList bringt dir keinen Vorteil, schränkt dich nur ein, es reicht wenn es eine beliebige List ist, das Interface bietet alle nötigen Methoden
 
Leider funktioniert da irgendwas immernoch nicht, vielleicht liegt es an den Temperaturen, dass es mir einfach nicht auffällt. Ich habe eigentlich alles umgesetzt was du mir empfohlen hast, denke ich.
Hier mein Code:
Java:
public static ArrayList<Procstep> anfragetest(String pgid, String db){
	int intpgid;
	intpgid = Integer.parseInt(pgid);
	System.out.println(intpgid);
	java.util.List<Integer> listepgid = anfraPgids(intpgid, db);
	String nuofpgid = "?";
	for(Integer s: listepgid){
	nuofpgid += " ?";
	}
	
	nuofpgid = nuofpgid.substring(0, nuofpgid.length()-2);
	ResultSet rs = null;
	PreparedStatement pstmt;
	Connection con = datenbankZugriff.dbverbindung.getConnection(db);
	ArrayList<Procstep> liste = new ArrayList<Procstep>();
	try {
		pstmt = con.prepareStatement("select process.name, processgroup.pgroupid,process.pid," +
				" processstep.seqnr, toolrelease.maincommand,processstep.status, " +
				"processstep.jobmachineid, processstep.psid, processinstance.pinid, " +
				"processstep.laststatuschange, processstep.priority, processinstance.startdate " +
				"from process,processgroup, processinstance,processstep,toolrelease where " +
				"process.pgroupid=processgroup.pgroupid and processgroup.pgroupid in ( " + nuofpgid + " ) and " +
				"process.pid = processinstance.pid and processinstance.pinid = processstep.pinid " +
				"and processstep.treleaseid = toolrelease.treleaseid and process.name not like " +
				"'Admin %\' order by process.pid,processinstance.startdate ASC, " +
				"processstep.seqnr, processstep.psid");
		int i = 1;
		for(Integer s: listepgid){
			pstmt.setInt(i++, s);	
			
		}
		rs = pstmt.executeQuery();

Bei der Instanziierung der List bin ich mir nicht sicher ob das so richtig ist.
Jedenfalls bekomme ich immernoch folgenden Fehler:
Java:
java.sql.SQLException: ORA-01745: invalid host/bind variable name

	at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
	at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:810)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
	at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:850)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1134)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3339)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3384)
	at datenbankZugriff.dbzugriff.anfragetest(dbzugriff.java:79)
	at tagHandler.test.main(test.java:16)

Den bekomme ich allerdings auch wenn ich als Liste die ArrayList benutze. Der String nuofpgid muss doch so bleiben oder nicht? Daraus kann ich doch kein Integer machen!?
 

Zurück
Oben