# Csv auslesen und in mysql db schreiben



## Dajule (19. Okt 2010)

Hallo erstmal
ich habe hier im Forum schon viele Antworten gefunden- aber auf dieses Poblem leider nicht , da muss ich wohl mal was verfassen.
Folgender Sachverhalt: ich (praktikantin, nicht mehr ganz aber schon noch anfängerin in java und ganz alleine- keine sau hat ahnung von Java) soll
aus einer csv datei Strings  einlesen und diese in eine mysql datenbank schreiben.
Ansatz 1: mysql bietet ja von sich aus die funktion an csv zu importieren- das habe ich versucht mit dieser methode:
[Java]   public void importData(Connection conn, String filename) {
            Statement stmt;
            String query;

            try {
                stmt = conn.createStatement(
                        ResultSet.TYPE_SCROLL_SENSITIVE,
                        ResultSet.CONCUR_UPDATABLE);

                query = "LOAD DATA INFILE '" + filename
                        + "' INTO TABLE mitarbeiter (mitarbeiternr,vname,nname,abteilung,position);";

                stmt.executeUpdate(query);

            } catch (Exception e) {
                e.printStackTrace();
                stmt = null;
            }
        }[/Java]
die methode rufe ich dann in der main mit entsprechender datenbankverbindung auf
und bekomme folgende fehler meldung:
com.mysql.jdbc.MysqlDataTruncation: 
Data truncation: Data too long for column 'mitarbeiternr' at row 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3489,3423,1936,2060,2536,1564,1485)

in meinem csv file steht als erstes , was ja schon scheitert eine 4 . ich habe die tabelle(die existiert nur zum testzweck) schon geändert und nun alles auf varchar(30) ohne pk stehen.was ist da nur zu lang?

okay ansatz 2:
dacht ich mir ich lade eben die strings aus dem csv file selber und habe dazu auch einen schönen code gefunden(ich glaube sogar hier im forum), der die strings aus dem csv in die konsole schreibt was auch wunderbar klappt.
nun will ich ja aber die strings übergeben a und so habe ich den code etwas modifiziert damit ich auch strings bekomme

```
public String formatCsv() {
		int max = list.size();
                int i;
                for( i=0; i<max; i++) {
                }
                return list.get(i).toString();
	    }
```

daraufhin bekomme ich ein outofbounds 
irgendwie scheint bei mir alles zu groß zu sein...


----------



## Sempah (19. Okt 2010)

Sowohl Variante 1 als auch Variante 2 müsste funktionieren, jedoch sind das zu wenig Informationen / Codeausschnitte, um zu beurteilen was da genau schief läuft.

Du könntest auch eine Klasse "Mitarbeiter" erstellen, die CSV parsen und pro Zeile (= 1 Datensatz) einen neues Mitarbeiter Objekt erzeugen und dieses bspw. einer Liste hinzufügen. Dann bräuchtest du nur noch eine Methode, welche die Mitarbeiter in die DB speichert.

So etwas in der Art:


```
private List<Mitarbeiter> mitarbeiterListe = new ArrayList<Mitarbeiter>();
		
	public void parseCsvDatei() {
		// CSV Datei laden und parsen
		// für jede Zeile:
		// mitarbeiterListe.add(new Mitarbeiter(...))
	}
	
	public void schreibeMitarbeiterInDb() {
		for (Mitarbeiter mitarbeiter : mitarbeiterListe) {
			String sql = "INSERT INTO mitarbeiter " + mitarbeiter.getMitarbeiternr() ", " + ...
		}
	}
```


----------



## Michael... (19. Okt 2010)

Zu Ansatz 1) habe nicht viel Erfahrung mit mySQL und keine mit dem Import von csv Daten, aber vielleicht stimmt ja etwas am Format der Datei nicht (Trennzeichen...) Man könnte ja mal einen Export als csv machen und die beiden Dateien vergleichen.
Zu Ansatz 2) Was soll diese Methode machen? Warum die leere Schleife?
Die Exception kommt daher, dass in Zeile 6) i = max ist und der letzte gültige Index aber max-1 ist.


----------



## AlexSpritze (19. Okt 2010)

Ich vermute bei Ansatz 1) musst du MySQL noch mitteilen, wie die CSV aufgebaut ist; zumindest bei phpMyAdmin muss die Spaltentrennzeichen (muss nicht unbedingt , = COMMA sein) und Zeilentrennzeichen explit angeben. Vielleicht steht da noch mehr zu der Syntax von LOAD DATA INFILE ...

Wenn du Zugriff auf die MySQL-DB per phpMyAdmin oder einem anderen Administrationstool hast, kannst du auch erstmal so versuchen, die Daten in die DB zu bekommen und dann per Java. Damit du überhaupt zumindest für Ansatz 1) das richtige SQL-Statement hast.



> in meinem csv file steht als erstes , was ja schon scheitert eine 4 . ich habe die tabelle(die existiert nur zum testzweck) schon geändert und nun alles auf varchar(30) ohne pk stehen.was ist da nur zu lang?



Vielleicht interpretiert er deine CSV-Datei als eine lange Zeile? Darum Trennzeichen explizit angeben oder so


----------



## Dajule (19. Okt 2010)

Danke für die schnellen  antworten- ich bin ja auch ein schaf wozu die leere schleife^^
ich hab ja schon eine liste von strings  in dem leerraum werde ich die nun passend formen.
und der tip mit dem csv format ist auch super danke ihr beiden hat mir schon echt weitergeholfen.


----------



## Dajule (25. Okt 2010)

so nun bin ich  dank eurer tips etwas weitergekommen- die csv direkt ein speisung läuft wie alex spritze schon richtig vermutet hat daran, dass mysql  erst noch gesagt werden muss wie es das importieren soll, nun hake ich allerdings daran, dass ich nichts finde womit ich das einstellen kann(phpmyadmin wehrt sich bei mir  leider immer fürchterlich).

habe deswegen mit plan b weitergemacht allerding fehlt mir da jetzt eine zündene Idee, die  vielleicht jemand von euch hat:

code soweit:
	
	
	
	





```
public class SQL {
        //Variablen für Datenbankverbindung
private Connection conn = null;
       
        //Variablen zum csv einlesen
private String zeile;
private ArrayList  liste = new ArrayList();
private String[] set = null; 

    public void dbconncet() throws ClassNotFoundException, SQLException{
      Class.forName("com.mysql.jdbc.Driver");
			// Datenbankverbindung herstellen
			conn = DriverManager
					.getConnection("jdbc:mysql://localhost/DB?"
							+ "user=root&password=PW");
                        loadCsv(); // Call Methode loadCcv

                        for(int i=1;i<5;i++){
                        Statement stmt = conn.createStatement();
                        stmt.executeUpdate("insert into mitarbeiter Values("+set[i]);
        }
        conn.close();
    }

    public void loadCsv()  // Csv einlesen und in Arraylist schreiben

    try {
				FileReader file = new FileReader("C:/mitarbeiter.csv");
				BufferedReader lies = new BufferedReader(file);
				while ((zeile = lies.readLine()) != null) {
					set = zeile.split(";");
					for(int i=0; i<set.length; i++) {
						//leere Zeilen ignorieren
						if( !(set[i].equals("")) )
						//eventuelle Leerzeichen zwischen zwei ';' entfernen
						//und Wert in Liste schreiben
						liste.add(set[i]);
					}
				}
		} catch (FileNotFoundException e) {
			System.out.println("Datei nicht gefunden");
		} catch (IOException e) {
			System.out.println("Eingabe-Fehler");
		}
}
```

nun ist allerdings meine liste noch nicht  richtig formatiert-ich bekomme also einen sql error:
right syntax to use near '' at line 1. Hat da vielleicht jemand eine Idee wie man das realisieren könnte, dass die Strings  für mysql lesbar formatiert werden- es reicht mir auch völlig wenn nur erstmal eine zeile eingelesen wir(immer schön step by step)- daher die forschleife erstmal nur bis 5.


----------



## Michael... (25. Okt 2010)

1. Zunächst mal steht in set nur der Inhalt der letzten Zeile.
2. Bist Du Dir sicher, dass set eine Länge von mindestens 6 hat? In der for-Schleife wird bis Index 5 eingelesen.
3. Wird Dein SQL statement nicht funktionieren, da die Tabelle MITARBEITER mindestens fünf Spalten besitzt. --> Wenn man eine Zeile nicht mit einem kompletten Datensatz befüllt, muss man auch angeben in welche Felder die Daten rein sollen.
4. Vermute ich, dass Du das gar nicht willst. (Du willst ja die Inhalt von set als ein Datensatz einfügen)
5. Wenn Dein Statement funktionieren würde, dann nur mit Zahlen
6. Mache zwischen durch immer mal ein paar Ausgaben mit System.out.println() (z.B. die Statements) oder benutze einen Debugger, damit kann man überprüfen, welche Werte einzelne Variablen besitzen.

Für später, wenn Du die ganze Datei so einlesen willst:
7. if( !(set_.equals("")) ) in Zeile 35 willst Du vermutlich auch nicht - nur weil ein Eintrag "leer" ist kann man ihn ja beim Import ignorieren._


----------



## Dajule (26. Okt 2010)

danke für die vielen denkanstöße - ups die tablenames hatt ich ganz vergessen^^
bin nun ein bischen weitergekommen und auf den nächsten haken gestoßen:
ich habe das nun erstmal als system out geschrieben, damit ich sehe wie die abfrage ausschaut ein insert kann ich ja draus machen wenn das statement korrent formatiert ist- danke für den rat michael


```
sql = ("insert into mitarbeiter(mitnr,vname,nname,abteilung,posi) Values(");
        for (i = 0; i < set.length; i++) {
            sql = sql + set[i] + " ','";
        }
        sql += ");";
        System.out.println(sql);
```
sieht ja auch schon  fast gut aus das statement :
insert into mitarbeiter(mitnr,vname,nname,abteilung,posi) Values(6 ','Susi ','Sorglos ','Schlafzimmer ','Gute Fee ',');
nur stehen da noch ein überflüssiges ',' am ende oder am anfang, die ich nicht wegbekomme- hab da auch keine gescheite methode für gefunden- gibts da nicht was einfaches?
habe  es mit 
	
	
	
	





```
sql.substring(sql.length()-2, sql.length()-3);
```
.
versucht aber da gibt es einen out of bounds fehler...
mein zweites problem ist wieso zu hölle nimmt er da nur die letzte zeile- es stehen 6 zeilen in meiner mitarbeiter.csv? was läuft da schon wieder schief?
und @Michael wieso meinst du, dass das statement nur mit zahlen funktionieren würde?


----------



## Michael... (26. Okt 2010)

Gundsätzlich könnte man - wie bereits erwähnt - eine Klasse Mitarbeiter o.ä. erstellen in der man die Attribute speichert.

Statt das Statement selbst zusammen zu basteln, würde ich ein PreparedStatement verwenden. Ist weniger rumgebastel und sicherer.

```
//Einmaliges Erzeugen einens PreparedStatements
PreparedStatement pstmt = con.prepareStatement("Insert into mitarbeiter values(?, ?, ?, ?, ?)");
...
//Befüllen des Statements im Programmablauf
pstmt.setInt(1, Integer.parseInt(set[0]));
for (int i=2; i<set.length; i++)
	pstmt.setString(i, set[i-1]);
//Ausführen des Statements
pstmt.executeUpdate();
```
Wenn Du bei dem selbstgebastelten Statement bleiben willst, musst Du halt das Zusammensetzen und die Schleife anpassen. Notfalls ohne Schleife Wert für Wert anfügen.


----------



## GIBMIRKRAFT (1. Nov 2010)

Hallo,

s.h. opencsv - Frequently Asked Questions

da ist bereits eine Lösung vorhanden...

Grüße


----------

