# Problem mit SUBSTR (Oracle) bzw. substring (Java)



## madman (20. Aug 2007)

Hallo, 

ich versteh die gerade überhaupt nichts mehr. Ich hab eine einfache Tabelle mit 3 Spalten: Titel, Name, Nummer. 
Bei Abfragen möcht aber nur die ersten 10 Zeichen haben. Oracle verarbeiten alle SQL Abfragen über die Konsole wunderbar, mit und ohne SUBSTR. Das komische ist nur, sobald ich ein SQL-Statement mit SUBSTR über JDBC (Version: 9.2.0.4.0) auf die Datenbank (lokal, Oracle 10g Express Edition) loslasse geht nichts mehr. 


Versuch 1)


```
String abfrageString = "Select SUBSTR(TITEL, 1, 10) from DATEN WHERE NUMMER=12345678"
```

Fehlermeldung: java.sql.SQLException: Ungültiger Spaltenname

Hat jemand eine Idee woran es liegen könnte?

Versuch 2)
Dann hab ich das Ganze folgender maßen versucht:


```
String Titel = result.getString("TITEL").substring(0, 10);
```
Fehlermeldung: Exception in thread "AWT-EventQueue-1" java.lang.StringIndexOutOfBoundsException: String index out of range: 10

Die Meldung kann ich schon nachvollziehen. Wird ausgelöst, weil an Stelle 10 nichts steht.

Wie kann ich aber alternativ die ersten 10 Zeichen eines Strings mit result.getString()... holen, auch wenn an der Stelle 10 nichts steht? 


Vielen Dank für eure Hilfe!

Gruß
Mike


----------



## abollm (20. Aug 2007)

madman hat gesagt.:
			
		

> [..]
> ich versteh die gerade überhaupt nichts mehr. Ich hab eine einfache Tabelle mit 3 Spalten: Titel, Name, Nummer.
> Bei Abfragen möcht aber nur die ersten 10 Zeichen haben. Oracle verarbeiten alle SQL Abfragen über die Konsole wunderbar, mit und ohne SUBSTR. Das komische ist nur, sobald ich ein SQL-Statement mit SUBSTR über JDBC (Version: 9.2.0.4.0) auf die Datenbank (lokal, Oracle 10g Express Edition) loslasse geht nichts mehr.
> 
> ...



Hm, mit welchem Java-Code hast du dein Resulset denn zuerst ausgegeben?

Du hast irgendeinen Fehler bei der Ausgabe deines Resultsets gemacht.

Wenn du ein SUBSTR-Beispiel für das SCOTT-Schema haben willst, dann melde dich, und ich poste dir ein funktionierendes Beispiel.

Hth


----------



## FenchelT (21. Aug 2007)

Hallo madman,

warum willst DU mittels java Funktion nochmals ein Substring machen, wenn das doch die DB schon fuer Dich erledigt hat?

Gib der Spalte im SELECT einen Namen und greif dann daruf zu.

SELECT SUBSTR(titel,1,10) as Titel FROM Tabelle


rs.getString("Titel");


Titel hat nurnoch 10 Zeichen.


Viele Gruesse
FenchelT


----------



## abollm (21. Aug 2007)

FenchelT hat gesagt.:
			
		

> [..]warum willst DU mittels java Funktion nochmals ein Substring machen, wenn das doch die DB schon fuer Dich erledigt hat?
> 
> Gib der Spalte im SELECT einen Namen und greif dann daruf zu.
> 
> ...



Das würde auch ohne das "as Titel" funktionieren. Somit ist das allein nicht die Ursache für den o.e. Fehler.


----------



## SnooP (21. Aug 2007)

Ich verstehe das nicht wirklich... ein:
Select SUBSTR(TITEL, 1, 10) from DATEN WHERE NUMMER=12345678

versucht doch nichts anderes als eine Spalte zurückzugeben, die das Ergebnis von SUBSTR(TITEL, 1, 10) ist und das kann ich mir beim besten Willen nicht vorstellen, wie das gehen soll 

du willst im Endergebnis nichts anderes als Titel mit maximal 10 Zeichen? Iteriere über alle Zeilen und mache mit dem String jeweils:

```
String res = result.getString("TITEL");
//pos 0 bis 9 sind die ersten 10 Zeichen
String neu = res.length() <=10 ? res.substring(0, 9) : res.substring(0, res.length() - 1);
```
Sprich nur dann die ersten 10 Zeichen zurückgeben, wenn auch genügend Länge da, sonst nur bis zur Länge zurückgeben.


----------



## FenchelT (21. Aug 2007)

abollm hat gesagt.:
			
		

> Das würde auch ohne das "as Titel" funktionieren. Somit ist das allein nicht die Ursache für den o.e. Fehler.



Bist DU sicher?

Ich wuerde bei 
sql =" SELECT substr(titel,1,10) FROM tabelle";

...
...
...

rs.getString("titel);

eine Fehlermeldung, ungueltiger Spaltenname erwarten.


Ausserdem macht es nach wie vor keinen Sinn, eine Datenbank-Funktion nochmals in JAVA abbilden zu wollen.

Wenn madman verstanden hat, dass ein "SELECT substr(titel, 1, 10)"  immer nur die ersten 10 Zeichen eines Titels erzeugt und er auch nur diese im ResultSet erwarten kann und auch nur dann, wenn er (und da bist Du ja anderer Meinung) auf rs.getString("substr(titel,1,10)") zugreift, dann hat er auch verstanden,
dass er die Java-Funktion nicht mehr benoetigt, da es nichts zu beschneiden gibt.

Es sei denn, er moechte die 10 Zeichen weiter reduzieren auf z.B. 5. Aber dann koennte er ja auch gleich im SQL ,1,15 schreiben.

Lasse mich aber gerne eines besseren belehren   :wink:


----------



## FenchelT (21. Aug 2007)

SnooP hat gesagt.:
			
		

> Ich verstehe das nicht wirklich... ein:
> Select SUBSTR(TITEL, 1, 10) from DATEN WHERE NUMMER=12345678
> 
> versucht doch nichts anderes als eine Spalte zurückzugeben, die das Ergebnis von SUBSTR(TITEL, 1, 10) ist und das kann ich mir beim besten Willen nicht vorstellen, wie das gehen soll
> ...




Hallo Snoop,

nein, ein substr(titel,1,10) versucht es nicht, es macht es, denn dafuer ist die DAtenbank Funktion da.
Und ALLES, was die DB machen kann, lass sie auch tun, denn dafuer ist sie ausgelegt.


Wenn Du Dir einen DS ausgeben moechtest, bei dem Du z.B. alle "SZ" durch "SELBST" ersetzen moechtest und zuaetzlich alle DS, die fuehrende "000" durch nichts ersetzen moechtest, ueber lasse es einfach der DB.

Soviel JAVA-Code kannst Du gar nicht soooo schnell tippen und ausfuehren, wie Dir die DB das Ergebnis geliefert hat.

select replace(left(replace(gkurz,'SZ', 'SELBST'),3),'000', '') + substring(gkurz,4,len(gkurz)) as replaced (Achtung MSSQL Syntax)


Viele Gruesse
FenchelT


----------



## abollm (21. Aug 2007)

FenchelT hat gesagt.:
			
		

> [..]
> Bist DU sicher?
> 
> Ich wuerde bei
> ...



Du musst schon richtig lesen (bitte alle Postings bis zu deinem ersten Posting) und dann richtig interpretieren. OK, das ist mitunter schwierig, gebe ich zu.

Gemeint war, dass das "...as TITEL..." allein, d.h. bei ansonsten keiner Veränderung des Codes (des OP!) für das obige Problem _sicher_ nicht _unbedingt_ zielführend ist.

Nachfolgend einmal Beispielcode in Auszügen, der im SCOTT-Beispielschema einwandfrei funktioniert:


```
[..]
	static String query = "select a.empno, substr(a.ename,1,2), a.job, "
		+ "a.mgr, to_char(a.hiredate, 'DD-Mon-YYYY HH24:MM:SS'), a.sal, a.comm, a.deptno FROM emp a";
[..]
		Statement stmt = conn.createStatement();
		// Query absetzen
		ResultSet rs = stmt.executeQuery(query);
		// Query verarbeiten …
		System.out.println("Ausgabe Datensätze\n");
		while (rs.next()) {
			empno = rs.getInt(1);
			ename = rs.getString(2);
			job = rs.getString(3);
			mgr = rs.getInt(4);
			hiredate = rs.getString(5);
			sal = rs.getInt(6);
			comm = rs.getInt(7);
			deptno = rs.getInt(8);
			System.out.println(empno + delim + ename + delim + job + delim
					+ mgr + delim + hiredate + delim + sal + delim + comm
					+ delim + deptno);
			//
		}
		rs.close();
[..]
```
Wie man sieht, ist ein "... as SPALTENNAME ..." nicht notwendig.
Das allein war von mir gemeint.

Ich arbeite ohnehin lieber mit den in meinem Code gezeigten Spaltenidizes anstatt mit expliziten Namen.


----------



## SnooP (21. Aug 2007)

FenchelT hat gesagt.:
			
		

> nein, ein substr(titel,1,10) versucht es nicht, es macht es, denn dafuer ist die DAtenbank Funktion da.
> Und ALLES, was die DB machen kann, lass sie auch tun, denn dafuer ist sie ausgelegt.


Ich wollte damit nur das selbe sagen, wie du - nämlich, dass ich bei der Syntax zumindest ebenfalls einen Column not found erwarten würde  - aaaaber nachdem ich es jetzt auch mal durchgespielt hab - bei mir funktioniert's sehr gut, mit genau dieser syntax: select substr(spalte, 1, 10) from tabelle;

Aaaber - wenn es nicht will - kann man ja evtl. doch auf diesen Java-Einzeiler zurückgreifen *g* - performancetechnisch sollte das keine Rolle spielen, da solcherlei String-Operationen mit Sicherheit kaum messbare Unterschiede machen werden 

edit:
ach gott - jetzt hab ich auch gerafft, was ihr mit dem "as TITLE" wolltet  - jo natürlich... ist halt die Frage an welcher Stelle jetzt überhaupt die Fehlermeldung geworfen wird und was im Resultset drin steht... debugging?


----------



## FenchelT (21. Aug 2007)

abollm hat gesagt.:
			
		

> Gemeint war, dass das "...as TITEL..." allein, d.h. bei ansonsten keiner Veränderung des Codes (des OP!) für das obige Problem _sicher_ nicht zielführend ist.




Hallo abollm,

ich  hoffe doch, dass ich alles gelesen und vor allem richtig gelesen habe  :wink: 

Aus meiner SIcht ist ein "... as Titel" sehr wohl zielfuehrend, da es ansonsten (mal abgesehen, man greift ueber den Spaltenindex zu) nicht funktionieren kann. Teste es doch einfach . Ich wette Du bekommst die Fehlermeldung:
Ungueltiger Spaltenname :wink: 

Das hier


> String Titel = result.getString("TITEL").substring(0, 10);



wird dann nicht mehr benoetigt, es reicht ein String Titel = result.getString("Titel");


Von daher halte ich meinen Tip sehr wohl fuer zielfuehrend.  Wenn es danach immer noch hakt, kann ich ja noch weiter fragen.


Dass Du lieber mit Spaltenindexen arbeitest als das Feld direkt anzusprechen musst Du fuer Dich entscheiden.
Ist ja okay, wenn Dir  sowohl die Datenbankadministration als auch die Entwicklung obliegt.

Mir als DB-Admin ist aber herzlich egal, wie ein Programmierer auf seine Daten zugreift.
Und wenn mir ein Projektleiter sagt, wir brauchen an Postion 4  in Tabelle X ein zusaetzliches Feld weil es im Zusammenhang mit den anderen Feldern steht, bekommt er an Position 4 dieses neue Feld.
Und ob dann ein Programmierer ploetzlich auf ein anderes Feld zugreift ist dann sein Problem.


Wie DU siehst, hat alles Vor- und Nachteile.


Aber da sich der Fragesteller nicht mehr gemeldet hat, gehe ich davon aus, dass sich das Problem wie auch immer geloest hat.

Falls DU Dich durch mich persoenlich angegriffen gefuehlt hast (hatte ein wenig das Gefuehl), so tut mir das natuerlich leid. Ich diskutiere immer nur um die Sache, nicht persoenlich und kann dann abends persoenlich trotzdem
noch mit dem anderen ohne Probleme ein Bier trinken gehen  :wink: 


In diesem Sinne, Dir noch einen schoenen Abend  

Viele Gruesse
FenchelT


----------



## abollm (21. Aug 2007)

@FenchelT

Kein Panik, ich bin ganz locker!

Dein Code und deine Bemerkungen sind ja in Ordnung. Der OP schrieb von drei Spalten in seiner DB. Ich bin davon ausgegangen, dass er auch die anderen Spalten abfragen möchte. Weil er von zwei (unterschiedlichen) Versuchen sprach, bin ich davon ausgegangen, dass er in seinem Resultset einen Fehler hatte (den er ja wohl auch ziemlich sicher hatte). Man kann den ORA-00904 aber auch problemlos mit meinem Code erzeugen.

Du bist sicher davon ausgegangen, dass er nur eine Spalte abfragen möchte, ich habe auch den allgemeinen Fall Bezug genommen.

Du hast Recht, ich habe mich unklar ausgedrückt. ;-)


----------



## abollm (21. Aug 2007)

@FenchelT:

Ach noch etwas, was mir gerade beim erneuten Nachdenekn des Threads aufgefallen ist:
Man sieht sehr gut, dass ein Erzeugen des Resultsets per Spaltennamen mindestens beim Einsatz von DB-Funktionen (Aggregat-, Package- und sonstigen SQL-Funktionen) eher problematisch ist, als die Spalten per Index anzusprechen. Letzteres hat zudem noch den Vorteil der aus meiner Sicht einfacheren dynamischen Generierung. Aber da wird es dann sicherlich "akademisch".

Gruß


----------



## FenchelT (21. Aug 2007)

@abollm



			
				abollm hat gesagt.:
			
		

> @FenchelT:
> 
> Ach noch etwas, was mir gerade beim erneuten Nachdenekn des Threads aufgefallen ist:
> Man sieht sehr gut, dass ein Erzeugen des Resultsets per Spaltennamen mindestens beim Einsatz von DB-Funktionen (Aggregat-, Package- und sonstigen SQL-Funktionen) eher problematisch ist, als die Spalten per Index anzusprechen.



Da hast Du sicherlich recht und das ist der Grund, warum ich bei solchen Diskussionen immer mit sehr viel Herzblut bei der Sache bin.  :wink: 

Man trifft in der Praxis unheimlich haeufig auf Leute, wie sie auch hier > " Core Java 2 Bd" erwaehnt werden.
Leute, die als Java-Programmierer fuer Wahr "Gurus" sind und am liebsten allles in Java abbilden.
SQL ist fuer viele dieser Leute nur mittel zum noetigsten Zweck, weil man kann es ja zur Not noch in Java umsetzen. :roll: 

Ich komme (leider?) von der anderen Seite. Ich bin in der Regel der Typ an der Datenbank, der bei SQL und Datenbank-Problemen weiterhilft (obwohl auch das nicht mein aktueller Job ist). 
Mir macht Java sehr viel Spass obwohl mein Wissen bei Weitem noch ueberschaubar ist.
So, wie ich hoffe, dass man mir bei meinen Java-Problemen weiterhilft helfe ich gerne den Leuten dabei SQL zu verstehen.

Und um auf Deine Aussage zurueck zukommmen, mir wuerde es nie in den SInn kommen, eine Aggregat- / String-Funktion ohne Spaltenalias zu benutzen. (das tippen die Finger automatisch  )

Viele Programmierer nutzen aber diese Funktionen ohne Alias einfach weil sie meinen "...wieso, ich gebe die Spalte doch in der Funktion an, dann werde ich sie auch zurueck bekommen).
Dann KOENNEN Fehler wie der o.g. auftreten 



> Letzteres hat zudem noch den Vorteil der aus meiner Sicht einfacheren dynamischen Generierung. Aber da wird es dann sicherlich "akademisch".
> 
> Gruß




Yap, da hast Du wohl recht  :wink: 


So long
FenchelT


----------



## madman (22. Aug 2007)

Hallo miteinander,

hat die letzten Tage Probleme mit meiner DSL Verbindung gehabt. Konnte deswegen leider nicht an der Diskussion teilnehmen. Vielen Dank für eure Anregungen.

@abollm. Die Ausgabe des Resultsets hab ich auch über das SCOTT-Schema gemacht (ohne zu wissen, dass es so genannt wird)

Bei Versuch 1) waren die Leerzeichen Schuld, dass die SQLException: Ungültiger Spaltenname ausgelöst wurde. Da hab ich mir aber ganz schön an den Kopf gelangt. 

Aus der Zeile

```
String abfrageString = "Select SUBSTR(TITEL, 1, 10) from DATEN WHERE NUMMER=12345678"
```
wurde folglich 

```
String abfrageString = "Select SUBSTR(TITEL,1,10) from DATEN WHERE NUMMER=12345678"
```
Keine Ahnung wieso, aber es funktionierte. Diese Möglichkeit (SUBSTR über SQL) hab ich aber wieder verworfen, weil mir aufgefallen ist, dass ich erstmal alle Zeichen benötige.

Bei Versuch 2) hab ich mich am Vorschlag von SnooP orientiert. Vor allem weil sein Vorschlag keine "String index out of range" Meldung auslöst. Also werde ich mit 

```
String res = result.getString("TITEL");
```
alles aus der DB holen und mit Java weitervearbeiten. 

Gruß
Mike


----------

