# SELECT liefert leere Zeilen



## geigenk (30. Jul 2009)

Hallo,

wenn dieses Thema in "Java Anfängerfragen" gehört bitte ich um Verschiebung. 
Bin Java und MySQL Anfänger, und möchte ein kleines Programm schreiben welches Zugriff auf eine MySQL Datenbank bietet, bisher müssen in der Eclipse Console die entsprechenden MySQL Befehle eingegeben werden.
Problem: Bei einer SELECT Abfrage wird die korrekte Anzahl an vorhandenen Zeilen geschrieben, jedoch ohne den entsprechenden Inhalt aus der Datenbank. Andere Abfragen wie SHOW TABLES funktionieren.
Was ist falsch oder fehlt? Vielen Dank schonmal!

Quellcode:

```
import java.io.*;
import java.sql.*;

public class test {
	public static void main(String[] args) {
	String treiber=null, DbUrl=null;
	treiber="com.mysql.jdbc.Driver";
	String host = "localhost";
	String port = "3306";
	String dbname = "testdb";
	String user = "testdb";
	String password = "testdb";
	try{
		Class.forName(treiber).newInstance();
		DbUrl = "jdbc:mysql://"+host+":"+port+"/"+dbname;
		DbUrl = DbUrl+"?useUnicode=yes&characterEncoding=UTF-8";
		Connection cn = DriverManager.getConnection(DbUrl,user,password);
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String command = null;
		while(true){
			System.out.print("MySQL Kommando:> ");
			command = in.readLine();
			if (command.equals("quit")) break;
			try{
				Statement st = cn.createStatement();
				ResultSet rs = st.executeQuery(command);
				while (rs!=null && rs.next()){
                	System.out.println(rs.getString(2));	
                }
				rs.close();
				st.close();
			} catch( SQLException ex){
				System.out.println(ex);   
			}
		}
		cn.close(); 
	}	catch(Exception ex) {
			System.out.println(ex);   
		}
	}
}
```


----------



## SlaterB (30. Jul 2009)

und die SELECT-Anfrage willst du nicht posten?
generell solltest du in Textprogrammen auf alle möglichen Eingaben, Zufallszahlen, externe Dateien usw. verzichten,

die Schleife kann auch weg, schreibe
command = "SELECT .. FROM ..";
direkt in den Quellcode,


----------



## geigenk (30. Jul 2009)

SlaterB hat gesagt.:


> und die SELECT-Anfrage willst du nicht posten?



Hab ich kein Problem mit .
Entsprechende Codeänderung:

```
if (command.equals("select")){
  command = "SELECT * FROM table1;";
  Statement st = cn.createStatement();
  ResultSet rs = st.executeQuery(command);
  while (rs!=null && rs.next()){
    System.out.println(rs.getString(1));
  }
  rs.close();
  st.close();
}
```
Brachte leider keinen Erfolg.
Es werden nur drei leere Zeilen entsprechend drei vorhandener Datensätze ausgegeben.


----------



## SlaterB (30. Jul 2009)

kann es sein, dass in der Tabelle an der Stelle nix steht?
bei den Indexen kann man sich ja auch vertun, ob nun 0 oder 1 die erste, zweite oder dritte Spalte ist..


----------



## geigenk (30. Jul 2009)

Tabelle enthält laut phpmyadmin folgendes:

Artikel 	Artikelnummer 	Anzahl
Artikel 1 	1 	                10
Artikel 2 	2 	                20
Artikel 3 	3 	                30

Habe auch schon verschiedene Spaltenindexe ausprobiert.

Danke schonmal für deine Bemühungen, bin erstmal bis heute Abend weg. Bis dann


----------



## headgrowe (31. Jul 2009)

hmmmm ich seh da in deinem code keinen fehler....ich poste einfach mal ein altes projekt von mir...da gehts 100%...bei mir....hast du primärschlüssel gesetzt? (kA ob das hier einfluss hat)

machs fürs erste nicht so kompliziert mit "try",(rs!=null),streaming und co...


```
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/java","root", "");
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,	ResultSet.CONCUR_UPDATABLE);
		ResultSet rs = st.executeQuery("select * from table1");
		ResultSetMetaData rsmd = rs.getMetaData();
		int nmax = rsmd.getColumnCount();
		while( rs.next() )
		{				
			for(int i=1 ; i<=nmax ; i++ ){
				System.out.print(rs.getString(i)+"   ");
			}
		System.out.println();
		}					
		rs.close();
		st.close();
```


----------



## geigenk (31. Jul 2009)

Vielen Dank für deine Hilfe.
Bei mir passiert mit deinem Code dasselbe wie mit meinem, Ausgabe besteht aus leeren Zeilen.
Kann das an irgendwelchen Eclipse Einstellungen liegen? Oder gibt es wie für C++ Ausgabebuffer die regelmäßig entleert werden müssen?



headgrowe hat gesagt.:


> hast du primärschlüssel gesetzt? (kA ob das hier einfluss hat)


Primärschlüssel hab ich keine gesetzt.


headgrowe hat gesagt.:


> machs fürs erste nicht so kompliziert mit "try",(rs!=null),streaming und co...


Streaming brauch ich weil ich die Datenbank im Dialog bearbeiten möchte.

Gruß


----------



## sparrow (31. Jul 2009)

Kommen denn überhaupt Zeilen an? Also läut die Schleife mehrmals durch?


----------



## Matt (31. Jul 2009)

hmmm also bei mir funktioniert dein Code wunderbar - überprüf einfach noch mal deine Konstanten werte wie URL und so - und ansonsten solltest du deine Datenbank mal abchecken... Hab dein Code einfach genommen (Copy&Paste) Einige konstante gändert wie username, password und DB URL und bei mir klappt das wunderbar

Wie gesagt: Check deine DB -> MySQL oder die konstanten werte nochmal (username, pw, URL) - es sollte sich auch empfehlen zu überprüfen wie die rechte des Users sind etc.


----------



## headgrowe (1. Aug 2009)

ob die schleife läuft is mal eine supa frage...wenn nicht, dann kommt auch nix an...
lad vielleich einen anderen dbtraiber runter...vl is da der fehler....

aber es liegt wh an den rechten...geh als root in die sqldb...weil wenn show table geht??!!


----------



## geigenk (3. Aug 2009)

Vielen Dank für eure Bemühungen!



sparrow hat gesagt.:


> Kommen denn überhaupt Zeilen an? Also läut die Schleife mehrmals durch?



Es existieren 3 Datensätze, 3 leere Zeilen werden in der Konsole ausgegeben.



Matt hat gesagt.:


> Check deine DB -> MySQL oder die konstanten werte nochmal (username, pw, URL) - es sollte sich auch empfehlen zu überprüfen wie die rechte des Users sind etc.



Rechte des Users sind großzügig vergeben, root liefert dasselbe Ergebnis.
Habe eine externe Datenbank zum Zugriff die nicht von mir ist, dort habe ich dasselbe Problem. SELECT * from xxx liefert bei Spalte 2-... 300+ leere Zeilen. Wenn allerdings Spalte 1 anzeigen lassen will stehen da die Zeilennummern.



headgrowe hat gesagt.:


> lad vielleich einen anderen dbtraiber runter...vl is da der fehler....



Es wäre schade wenn das mit JDBC nicht funktioniert, war schon glücklich so weit gekommen zu sein. Beste Alternative wäre ODBC?


----------



## sparrow (3. Aug 2009)

geigenk hat gesagt.:


> as mit JDBC nicht funktioniert, war schon glücklich so weit gekommen zu sein. Beste Alternative wäre ODBC?



Nein. Der JDBC-Treiber ist ausgereift. Ein Wechsel auf die JDBC/ODBC-Bridge ist ein Schritt in die Steinzeit. Wobei die Bridge nur als Übergangslösung gedacht war bis die JDBC-Treiber zur Verfügung standen.

Machen wir ein einfaches kleines Beispiel (ohne Test, ich arbeite nicht mit mySQL):


```
import java.io.*;
import java.sql.*;

public class test {
	public static void main(String[] args) {
	String treiber=null, DbUrl=null;
	treiber="com.mysql.jdbc.Driver";
	String host = "localhost";
	String port = "3306";
	String dbname = "testdb";
	String user = "testdb";
	String password = "testdb";
	try{
		Class.forName(treiber).newInstance();
		DbUrl = "jdbc:mysql://"+host+":"+port+"/"+dbname;
		DbUrl = DbUrl+"?useUnicode=yes&characterEncoding=UTF-8";
		Connection cn = DriverManager.getConnection(DbUrl,user,password);
		while(true){
			try{
				Statement st = cn.createStatement();
				ResultSet rs = st.executeQuery("SELECT COUNT(*) AS anzahl FROM table1;");
				rs.next();
                	System.out.println("Datensätze in der Tabelle: " + rs.getInteger("anzahl"));	
                }
				rs.close();
				st.close();
			} catch( SQLException ex){
				ex.printStackTrace();  
			}
		}
		cn.close(); 
	}	catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}
```

Ich hoffe das klappt ohne Syntaxfehler.
Was ist denn dann die Ausgabe des Programms?

Ahso, und wenn Exceptions fliegen wäre natürlich gut zu wissen in welcher Zeile und welcher Typ von Exception. Du hast in deinem Code nämlich keinen StackTrace ausgegeben.


----------



## geigenk (3. Aug 2009)

Ausgabe ist:

```
Datensätze in der Tabelle: 3
```

Exceptions treten keine auf, sind es auch bisher nicht, ausser wenn ich testweise Fehler eingebaut habe.
Oder meintest du eine generelle Ausgabe des StackTrace unabhängig von Exceptions? Wie das geht weiss ich leider nicht.

Edit:
Im Code die while Schleife rausgenommen und
"getInteger" geändert in "getInt"


----------



## geigenk (3. Aug 2009)

Das habe ich mal an verschiedenen Stellen im Code ausprobiert.

```
for ( StackTraceElement trace : new Throwable().getStackTrace() ){
   System.out.println( trace );
}
```
Gibt die jeweilige Position des Schnipsels im Code aus. Vermute mal entweder dass das nicht viel bringt weil ich keine weiteren Funktionen im Einsatz habe oder das Codeschnipsel macht hier generell keinen Sinn.


----------



## sparrow (3. Aug 2009)

```
import java.io.*;
import java.sql.*;
 
public class test {
    public static void main(String[] args) {
    String treiber=null, DbUrl=null;
    treiber="com.mysql.jdbc.Driver";
    String host = "localhost";
    String port = "3306";
    String dbname = "testdb";
    String user = "testdb";
    String password = "testdb";
    try{
        Class.forName(treiber).newInstance();
        DbUrl = "jdbc:mysql://"+host+":"+port+"/"+dbname;
        DbUrl = DbUrl+"?useUnicode=yes&characterEncoding=UTF-8";
        Connection cn = DriverManager.getConnection(DbUrl,user,password);
            try {
                Statement st = cn.createStatement();
                ResultSet rs = st.executeQuery("SELECT * FROM table1;");
		int columncount = rs.getMetaData().getColumnCount();
		int rowcount = 0;
		System.out.println("Die Tabelle hat offensichtlich " + columncount + " Spalten...");
		while (rs.next()) {
	           rowcount++;
                   System.out.println("==== Datensatz Nr. " + rowcount + " ====");
                    for (int i = 1; i <= columncount; i++) {
                       System.out.println(rs.getMetaData().getColumnName(i) + " : " + 
			  rs.getString(i);
                    }
		}
                rs.close();
                st.close();
            } catch( SQLException ex){
                ex.printStackTrace();  
            }
        cn.close(); 
    }   catch(Exception ex) {
            ex.printStackTrace();
        }
    }
}
```

Wieder aus dem Kopf angepasst, ggf. Compilerfehler beheben.

Die Ausgabe bitte.


----------



## geigenk (3. Aug 2009)

```
Die Tabelle hat offensichtlich 3 Spalten...
==== Datensatz Nr. 1 ====
Artikel :
Artikelnummer : 1
Anzahl : 10
==== Datensatz Nr. 2 ====
Artikel : 
Artikelnummer : 2
Anzahl : 20
==== Datensatz Nr. 3 ====
Artikel :
Artikelnummer : 3
Anzahl : 30
```

Die Typen von Spalte 2 und 3 sind jeweils INT, Spalte 1 ist TEXT. Wenn ich Spalte 1 lösche werden alle Datensätze korrekt angezeigt.
-> getString kann mit TEXT nichts anfangen?


----------



## sparrow (3. Aug 2009)

Vielleicht statt TEXT VARCHAR verwenden? Bei Postgres kann man zwar TEXT nehmen, ich meine mich aber zu erinnern, dass da bei mySQL eine von vielen Schwierigkeiten lag.


----------



## geigenk (3. Aug 2009)

Oh mann... Kollation der Tabelle stand auf schwedisch, weiss der Geier weshalb. Nach Umstellen auf UTF-8 wurde der Text korrekt angezeigt.

-> grandios. 

Ich bitte um Verzeihung. Habe große Lust der Runde hier ne Runde Bier zu spendieren :toll:. Dank besonders an sparrow.

Leider ist das Ursprungsproblem noch nicht 100%ig gelöst. Meine Datenbank ist jetzt korrekt eingestellt und wird in der Konsole korrekt angezeigt. Die Fremddatenbank jedoch, auf die ich eigentlich zugreifen will, beschert mir immernoch leere Einträge in den Spalten in denen der Typ Text/String/Char ist.
Wie kann ich jetzt herausfinden welche Kollation dort eingestellt ist? Habe nur Gastzugang, mit MySQL Admin oder OpenOffice Base habe ich es nicht herausgefunden.


----------



## SlaterB (3. Aug 2009)

TEXT ist nun wirklich kein normaler StringTyp,
vielleicht funktioniert allgemein eher
resultSet.getAsciiStream()
resultSet.getBinaryStream()
resultSet.getBlob()


nicht direkt zu diesem Thema, aber schönes PDF zu Datei + SQL in Java, welches ich dabei gefunden habe:
http://deissler.de.funpic.de/schule/java/DBundJava.pdf


----------



## geigenk (3. Aug 2009)

Diese drei Methoden haben leider auch nicht funktioniert, sie liefern je Eintrag zB sowas:

```
java.io.ByteArrayInputStream@867a08
```

Danke für das PDF, ist ganz hilfreich für grundlegende Sachen.

Werde mal weitersuchen.


----------



## SlaterB (3. Aug 2009)

aus einem Stream muss man mit read() lesen usw., nicht trivial,
aber in dem PDF steht anfangs auch was zum Einlesen aus Dateien, da lernst du gleich was über Streams


----------



## sparrow (3. Aug 2009)

geigenk hat gesagt.:


> Diese drei Methoden haben leider auch nicht funktioniert, sie liefern je Eintrag zB sowas:
> 
> ```
> java.io.ByteArrayInputStream@867a08
> ...



Das liegt aber eher daran, dass ein Stream so nicht ausgelesen wird  Da verrät dir aber "Java ist auch eine Insel" oder www.javabuch.de - Das Handbuch der Java-Programmierung mehr.
Die einfachste Lösung dürfte es allerdings sein einfach den richtigen Spaltentyp zu wählen, und das ist für eine Artikelbezeichnung kein TEXT.


----------



## headgrowe (3. Aug 2009)

ok...das war echt strage....ich verwende immer getString^^ ob INT oder TEXT drinnen steht.... hat dein externer server keinen myAndmin zugang?!....mein externer server geht bis jt leider auch nocht nicht...er sagt immer ich hab den falschen server...also suche auch noch einen free serven, wenn wer einen kennt^^


----------



## sparrow (3. Aug 2009)

headgrowe hat gesagt.:


> ok...das war echt strage....ich verwende immer getString^^ ob INT oder TEXT drinnen steht.... hat dein externer server keinen myAndmin zugang?!....mein externer server geht bis jt leider auch nocht nicht...er sagt immer ich hab den falschen server...also suche auch noch einen free serven, wenn wer einen kennt^^



Ich kann dir nicht ganz folgen, aber in der Regel wirst du kaum einen Anbieter finden der dir (z.B. bei Webspace) erlaubt von extern auf den Socket der Datenbank zu verbinden. Schon aus Sicherheitsgründen ist das nur lokal an der Maschine möglich (sprich mit einem auf dem Server ausgeführten Programm)


----------



## headgrowe (3. Aug 2009)

wie, ich will ja nur daten aus der db auslesen und dann schreiben?! is das nicht egal von wo...
is doch das gleiche wie mit php...also dachte ich^^


----------



## sparrow (3. Aug 2009)

headgrowe hat gesagt.:


> wie, ich will ja nur daten aus der db auslesen und dann schreiben?! is das nicht egal von wo...
> is doch das gleiche wie mit php...also dachte ich^^



Ist es nicht. PHP wird auf dem Server ausgeführt und greift daher auf localhost zu.
Solange dein Java-Programm also nicht auf dem Server läuft wird das mit den typischen Webspace-Anbietern ganz einfach nicht funktionieren. Applets und Webstart-Anwendungen werden übrigen lokal auf dem Client ausgeführt, nicht auf dem Server.
Selbstverständlich kann man mit Java auf Datenbankserver zugreifen die nicht der eigene Rechner (localhost) sind. Allerdings kann man mySQL sehr einfach sagen "akzeptiere nur Datenbankverbindungen von localhost". Somit fällt, falls nicht Serverseitig ausgeführt, Java in solchen Fällen flach.


----------



## headgrowe (3. Aug 2009)

thats written on the webside i have the sql server....(db4free.net - Databases for free: get a free MySQL database account (MySQL 5.1))


```
You can restrict access to your database account to a specific IP address or host to increase the security of your account. If you want to limit access to your PHP files that are hosted at your ISP, you can enter your ISP's hostname or IP address. Entering a more specific value than the percent sign (which gives you access from any host), makes it impossible to access your account from anywhere else (including hackers).
```

therefore i thougth it is possible connection from outside^^


----------



## soulgecko (3. Aug 2009)

@headgrowe: Eh ich hoffe für dich, dass weder Englisch noch Deutsch deine Muttersprache ist...


----------



## headgrowe (4. Aug 2009)

ups ja stimmt da sind fehler^^ jep, meine muttersprache is tschechisch^^


----------



## geigenk (4. Aug 2009)

SlaterB hat gesagt.:


> aus einem Stream muss man mit read() lesen usw., nicht trivial,
> aber in dem PDF steht anfangs auch was zum Einlesen aus Dateien, da lernst du gleich was über Streams



Habe dies beherzigt, weiter unten der neue Quellcode zu dem ich wieder Fragen habe.



sparrow hat gesagt.:


> Das liegt aber eher daran, dass ein Stream so nicht ausgelesen wird  Da verrät dir aber "Java ist auch eine Insel" oder www.javabuch.de - Das Handbuch der Java-Programmierung mehr.
> Die einfachste Lösung dürfte es allerdings sein einfach den richtigen Spaltentyp zu wählen, und das ist für eine Artikelbezeichnung kein TEXT.



Für die externe Datenbank steht die Option der Wahl des richtigen Spaltentyps leider nicht, da sie nicht von mir ist. Allerdings bin ich jetzt auf dem Stream-Kurs, denke das wird hinhauen.



headgrowe hat gesagt.:


> ok...das war echt strage....ich verwende immer getString^^ ob INT oder TEXT drinnen steht.... hat dein externer server keinen myAndmin zugang?!....mein externer server geht bis jt leider auch nocht nicht...er sagt immer ich hab den falschen server...also suche auch noch einen free serven, wenn wer einen kennt^^



Ganz bestimmt hat der Besitzer einen Admin Zugang, aber ich vermute auch dass der nur lokal zugänglich ist, falls nicht bekomme ich den Zugriff auch nicht .

So nun mein neuer Code:

```
try {
	            	DataInputStream input;
	            	byte b;
                	String tmpstr = "";
	                Statement st = cn.createStatement();
	                ResultSet rs = st.executeQuery("SELECT * FROM table1;");
	                int columncount = rs.getMetaData().getColumnCount();
	                int rowcount = 0;
	                System.out.println("Die Tabelle hat offensichtlich " + columncount + " Spalten...");
	                while (rs.next()) {
	                	rowcount++;
	                	System.out.println("==== Datensatz Nr. " + rowcount + " ====");
	                    for (int i = 1; i <= columncount; i++){
                    		input = new DataInputStream(rs.getBinaryStream(i));
                    		tmpstr = "";
                    		b = 0;
                    		if (true){
                    			while ((b=(byte)input.read())!=-1){
                    				tmpstr = tmpstr + (char)b;
                    			}
                    		}
                    		input.close();
	                    	System.out.println(rs.getMetaData().getColumnName(i) + " : " + tmpstr);
	                    }
	                    if (rowcount>20) break;
	                }
	                rs.close();
	                st.close();
	            } catch( SQLException ex){
	            	ex.printStackTrace();  
	            }
```

Dies führte einen bedeutenden Schritt weiter. Alle Inhalte der jeweiligen Spalte wurden einwandfrei ausgegeben, allerdings wenn die Schleife auf einen leeren Eintrag traf wurde eine Exception geworfen:


```
java.lang.NullPointerException
   at java.io.FilterInputStream.read(libgcj.so.90)
   at mysqltest.b(mysqltest.java:91)
   at mysqltest.main(mysqltest.java:15)
```

Zeile 91 entspricht Zeile 18 oben.
Habe versucht dies mit einer Abfrage ob input.equals(null) oder input.available() > 0 abzufangen, jedoch ohne Erfolg, denn dann wurde die Exception von dieser Zeile aus geworfen.


----------



## woezelmann (4. Aug 2009)

versuchs mal mit 
	
	
	
	





```
input != null
```
 abzufangen


```
input.equals(null)
```
 ist auch ein Methodenaufruf, und der funktioniert nicht, wenn auf null gezeigt wird ...

btw.: wusste gar nicht das so was geht, man lernt nie aus


----------



## SlaterB (4. Aug 2009)

input wird nicht null sein, die Exception findet im Reader statt
wahrscheinlich ist rs.getBinaryStream(i) null, das kann man auch prüfen

> if (true){

interessant


----------



## geigenk (4. Aug 2009)

SlaterB hat gesagt.:


> input wird nicht null sein, die Exception findet im Reader statt
> wahrscheinlich ist rs.getBinaryStream(i) null, das kann man auch prüfen



Punktlandung. Ich bin begeistert, es läuft. Vielen Dank!



SlaterB hat gesagt.:


> > if (true){
> 
> interessant


Platzhalter 


Hier der funktionierende Code:

```
try {
	            	DataInputStream input;
	            	byte b;
                	String tmpstr = "";
	                Statement st = cn.createStatement();
	                ResultSet rs = st.executeQuery("SELECT * FROM mgmtPublics;");
	                int columncount = rs.getMetaData().getColumnCount();
	                int rowcount = 0;
	                System.out.println("Die Tabelle hat offensichtlich " + columncount + " Spalten...");
	                while (rs.next()) {
	                	rowcount++;
	                	System.out.println("==== Datensatz Nr. " + rowcount + " ====");
	                    for (int i = 1; i <= columncount; i++){
                    		input = new DataInputStream(rs.getBinaryStream(i));
                    		tmpstr = "";
                    		b = 0;
                    		if (rs.getBinaryStream(i) != null){
                    			while ((b=(byte)input.read())!=-1){
                    				tmpstr = tmpstr + (char)b;
                    			}
                    			input.close();
                    		}
	                    	System.out.println(rs.getMetaData().getColumnName(i) + " : " + tmpstr);
	                    }
	                    if (rowcount>20) break;
	                }
	                rs.close();
	                st.close();
	            } catch( SQLException ex){
	            	ex.printStackTrace();  
	            }
	            cn.close();
```
Werde ihn noch optimieren, dann kann ich endlich den Dialog wieder einbauen.

Danke euch allen, bin wirklich froh. Gutes Forum


----------

