# Importieren in MySQL mit Java-Programm



## bertram (19. Okt 2006)

Guten Tag,

ich schreibe gerade ein Java-Programm, mit dem ich auf eine MySQL Datenbank zugreife.
Eine funktion dieses Programms ist es Dateien zu importieren, es funktioniert auch, bisher gebe ich den Pfad im Java-Quelltext an.
Ich möchte es aber so machen, das sich ein Fenster öffnet und ich mir die Datei zum importieren aussuchen kann, so als wenn ich z. B. in Excel auf "Datei öffnen" klicke.
Dies ganze soll mit einem klick auf ein Button geschehen.

Schon einmal vielen Dank im voraus.

MfG

bertram


----------



## Xandro (19. Okt 2006)

Moin,

schau Dir mal den JFileChooser an:

http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JFileChooser.html


----------



## The_S (19. Okt 2006)

rofl :lol: .


----------



## bertram (19. Okt 2006)

Erstmal vielen dank für die rasch Antwort.

Dies ist mein Quellcode:

```
Frame frame = new Frame();
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showOpenDialog(frame);
if(returnVal == JFileChooser.APPROVE_OPTION) 
{
        try
        {
            System.out.println("* Verbindung aufbauen");
            String url = "jdbc:mysql://"+hostname+":"+port+"/"+dbname;
            conn = DriverManager.getConnection(url, user, pw);
        }
        catch (SQLException sqle)
        {
            System.out.println("SQLException: " + sqle.getMessage());
            System.out.println("SQLState: " + sqle.getSQLState());
            System.out.println("VendorError: " + sqle.getErrorCode());
            sqle.printStackTrace();
        }
        
        Statement stmt;
        String query;
        try
        {
            stmt = conn.createStatement();
            query = "LOAD DATA INFILE '"+selFile+"' INTO TABLE importtabelle_rohdaten;";

            stmt.executeUpdate(query);
            stmt.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            stmt = null;
        }
        }
```

Er findet die ausgewählte Datei aber nicht.
Ich bekomme die Fehlermeldung:
java.sql.SQLException: File 'C:Importtabelle_rohdaten.txt' not found (Errcode: 2)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)

Schon einmal vielen Dank im voraus.

MfG

bertram


----------



## The_S (19. Okt 2006)

Ich weiß zwar nicht, was das Statement "LOAD DATA INFILE" macht, aber imho könntest du mal probieren alle Backslashes in deinem Pfad doppelt zu maskieren bzw. durch normale Slashes zu ersetzen.


----------



## bertram (19. Okt 2006)

Das habe ich mir auch gedacht, da MySQL ja nur normale Slashes zur pfadangabe akzeptiert.

Aber wenn ich eine File mit dem jFileChooser auswähle, setzt er automatisch Backslash für den Pfad ein.
Wie kann ich den jFileChooser den so einstellen, das er die normalen Slashes benutzt?

"LOAD DATA INFILE" ist das MySQL Statement um Dateien in eine MySQL DB zu importieren.


----------



## The_S (19. Okt 2006)

```
String pfad = filechooser.getSelectedFile().getAbsolutePath().replace('\\', '/');
```


----------



## bertram (19. Okt 2006)

Danke, jetzt funktioniert es einwandfrei.


----------



## bertram (20. Okt 2006)

Ich habe gerade erfahren, das noch eine weitere Anforderung an das Programm gestellt wird.
Vorher wurde ein MS Access Programm benutzt, das Programm hat vor dem Import gefragt, welches Zeichen als Trennzeichen benutzt werden soll.
Dies soll jetzt auch im Java-Programm geschehen.

Ich habe dies bezüglich einige Fragen:

1.
Die zu importierende Datei ist eine csv Datei, die Daten sind also nicht mit Tabulator getrennt, so wie es MySQL benötigt.
Wie kann ich das so einstellen, das Tabulator als Trennzeichen verwendet wird?

2.
In der csv Datei haben die Spalten Überschriften, die nicht mit in die Datenbank importiert werden sollen.
Wie kann ich das auslesen der Zeile umgehen?

Hier ist mein Quellcode vom Import:

```
Frame frame = new Frame();
        JFileChooser chooser = new JFileChooser();
        int returnVal = chooser.showOpenDialog(frame);
        if(returnVal == JFileChooser.APPROVE_OPTION) 
        {
            File selFile = chooser.getSelectedFile();
            System.out.println("Ausgesuchte Datei: "+selFile.getName()); 
            
            String pfad = chooser.getSelectedFile().getAbsolutePath().replace('\\', '/');
        
            Statement stmt;
            String query;
            try
            {
                stmt = conn.createStatement();
                query = "LOAD DATA INFILE '"+pfad+"'FIELDS TERMINATED BY'   ' INTO TABLE importtabelle_rohdaten;";
                stmt.executeUpdate(query);
                stmt.close();
            }
            catch(Exception e)
            {
                e.printStackTrace();
                stmt = null;
            }
        }
```

Schon einmal vielen Dank im voraus.

MfG

bertram


----------



## The_S (20. Okt 2006)

Ohne näheres Hintergrundwissen ob das SQL-Seitig realisierbar ist, würde ich sagen, dass du die Datei auslesen, nicht benötigte Elemente rausschneiden und anschließend die veränderte Datei speichern musst. Um Anschließend deine neue Datei als Vorlage verwenden zu können. Evtl. geht es auch einfacher, aber mir fällt sonst kein Weg ein


----------



## bertram (24. Okt 2006)

```
JFileChooser chooser = new JFileChooser();
        int returnVal = chooser.showOpenDialog(frame);
        if(returnVal == JFileChooser.APPROVE_OPTION) 
        {
            File selFile = chooser.getSelectedFile();
            System.out.println("Ausgesuchte Datei: "+selFile.getName()); 
            
            String pfad = chooser.getSelectedFile().getAbsolutePath().replace('\\', '/');
            
            Statement stmt;
            String query;
            try
            {
                stmt = conn.createStatement();
                query = "LOAD DATA LOCAL INFILE '"+pfad+"' INTO TABLE importtabelle fields terminated by ';' enclosed by '\"' lines terminated by '\r\n' ignore 1 lines";
                stmt.executeUpdate(query);
                stmt.close();
            }
            catch(Exception e)
            {
                JOptionPane.showMessageDialog(null,"SQLException: "+e.getMessage()+"\n"+e.getStackTrace(),"Fehler",JOptionPane.ERROR_MESSAGE);
                stmt = null;
            }
        }
```

So habe ich mein Problem gelöst.


----------



## bertram (10. Jan 2007)

Hallo,

Der Import klappt jetzt einwandfrei, nur habe ich jetzt ein paar andere Probleme, die Daten die ich importiert habe, sollen mit schon vorhandenen Daten aus einer anderen Tabelle verglichen und ggf. soll die andere Tabelle dann aktualisiert werden.
Ich beschreibe es mal anhand von meinem Programm, es gibt die Tabelle "Importtabelle_Rohdaten", in der die Daten importiert werden und die Tabelle "Alle_Bestellungen", mit der die Daten aus der Tabelle "Importtabelle_Rohdaten" verglichen und halt ggf. aktualisiert werden sollen.

Meine erste Frage ist:
Wie kann ich in Java zwei MySQL Tabellen vergleichen?

Nachdem die Daten importiert und verglichen wurden, sollen die Daten in der Tabelle "Alle_Bestellungen" aktualisiert werden.

Meine zweite Frage ist:
Wie kann ich in Java die Tabelle "Alle_Bestellungen", anhand der Daten aus der Tabelle "Importtabelle_Rohdaten aktualisieren?

Schon einmal vielen Dank im voraus.

MfG

Bertram


----------



## DaKo (10. Jan 2007)

> Wie kann ich in Java zwei MySQL Tabellen vergleichen?


Was ist dein Vergleichskriterium?



> Wie kann ich in Java die Tabelle "Alle_Bestellungen", anhand der Daten aus der Tabelle "Importtabelle_Rohdaten *aktualisieren*?



definiere aktualisieren! Noch nicht vorhandene Datensätze hinzufügen? Bereits vorhandene Datensätze überschreiben?


----------



## Yzebär (10. Jan 2007)

Am einfachsten ist es ein select-Statement zu schreiben, daß dir alle Zeilen der Rohdaten liefert die neu sind (select * from rohdaten r where (count(*) from alle_bestellungen where r.id = id) = 0 ). Wenn du das Resultset nicht direkt über SQL in die andere Tabelle einfügen kannst, mußt du es zeilenweise auslesen und ein insert machen.
Analog machst du es mit den Daten die aktualisiert werden müssen, du änderst das select-Statement so ab, daß du alle Zeilen zurückbekommst, deren ID schon in der Tabelle der Bestellungen vorhanden ist. Dann setzt du zeilenweise ein update ab.

Mit ID ist eine eindeutige Identifizierung gemeint (zB Rechnungsnummer).


----------



## bertram (10. Jan 2007)

Erstmal danke für eure schnelle Hilfe.

1. Meine Vergleichskriterien sind die Spalten "BestellNr" und "Position"(das ist der PK), ich mache am besten eben schnell ein Beispiel.

Alle_Bestellungen
BestNr(PK)	Position(PK)	Name	Bedarfsdatum
123		    50		Welle	25.10.2006
456		75		Rohr	24.12.2006

Importtabelle_Rohdaten
BestNr(PK)   Position(PK)        Name                 Bedarfsdatum
123              50                      Welle                 30.10.2006
456              75                      Rohr                  16.12.2006
789              88                      Radio                 22.05.2007

Ich habe das Programm jetzt so weit, das es vorhandene Datensätze überschreibt, das heißt die ersten beiden Positionen werden überschrieben.
Aber die dritte Position wird nicht mit in die Tabelle übernommen.

Ich hoffe das Beispiel verdeutlicht mein Problem, und beantwortet alle offenen Fragen.

Hier ist mein Quellcode:


```
JFileChooser chooser = new JFileChooser();
        chooser.addChoosableFileFilter(new FileFilter() 
        {
            public boolean accept(File f) 
            {
                if (f.isDirectory()) return true;
                return f.getName().toLowerCase().endsWith(".csv");
            }
            public String getDescription ()
            { 
                return "CSV"; 
            } 
        }
        );
        if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)
        {
            File selFile = chooser.getSelectedFile();
            System.out.println("Ausgesuchte Datei: "+selFile.getName()); 
            
            String pfad = chooser.getSelectedFile().getAbsolutePath().replace('\\', '/');
            System.out.println("Pfad: "+pfad);
            Statement stmt;
            String query;
            try
            {
                stmt = conn.createStatement();

                //Daten werden in die Tabelle "Importtabelle_Rohdaten" geschrieben
                stmt.executeUpdate("LOAD DATA LOCAL INFILE '"+pfad+"' INTO TABLE importtabelle_rohdaten fields terminated by ';' enclosed by '\"' lines terminated by '\r\n' ignore 1 lines");
                
                //Daten aus "Importtabelle_Rohdaten" werden mit den Daten aus der Tabelle "Alle_Auftraege verglichen und uebertragen"
                stmt.executeUpdate("UPDATE alle_auftraege,importtabelle_rohdaten set alle_auftraege.Bedarfsdatum=importtabelle_rohdaten.Bedarfsdatum" +
                        ",alle_auftraege.ABLief=importtabelle_rohdaten.ABLief,alle_auftraege.Bemerkung=importtabelle_rohdaten.Bemerkung " +
                        "where alle_auftraege.BestNr=importtabelle_rohdaten.BestNr and alle_auftraege.Position=importtabelle_rohdaten.Pos");
                
                //Daten werden aus der Tabelle "Importtabelle_rohdaten" wieder entfernt
                stmt.executeUpdate("DELETE FROM importtabelle_rohdaten");
                
                stmt.close();
                
            }
            catch(Exception e)
            {
                JOptionPane.showMessageDialog(null,"SQLException: "+e.getMessage()+"\n"+e.getStackTrace(),"Fehler",JOptionPane.ERROR_MESSAGE);
                stmt = null;
            }
        }
```

Schon einmal vielen Dank im voraus.

MfG

Bertram


----------



## Yzebär (10. Jan 2007)

Für die dritte Position mußt du ein insert machen. Ich glaube es geht mit select into... also select * into alle_auftraege from import_daten where ... PK nicht in alle_auftraege vorhanden.

Du kannst auch nach deinem UPDATE alle Einträge löschen, die schon übernommen wurden und dann das select * into ohne where ausführen lassen.


----------

