# Datenbank Statement



## Genkin (13. Aug 2019)

Hallöle

Ich habe eine MS Access DB. Die Verbindung an sich besteht auch.
Ich möchte nun eine SQL Abfrage durchführen. Diese Abfrage steht in einer for-Schleife, weil ich keine Lust habe, 20x den SQL-Befehl umzuändern. Die Werte im int[] kostenstellen sind dann die Einträge, nach denen ich suchen will. Ich bekomme aber immer die unten aufgeführte Fehlermeldung mit "Column not found: 0". Der Spaltenname ist aber KstStNr, so wie er auch in dem SQL-Befehl steht... Weiß jemand ne Lösung??
Später will ich für jede "KstStNr", bestehend aus mehreren WHERE Bedingungen (noch ausgeklammert) die Summe der Werte berechnen und speichern.


Fehlermeldung:


```
1. Summe: net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::4.0.1 Column not found: 0
    at net.ucanaccess.jdbc.UcanaccessResultSet.getInt(UcanaccessResultSet.java:447)
    at DBConnection.holDbDaten(DBConnection.java:97)
    at Main.main(Main.java:8)
Caused by: java.sql.SQLException: Column not found: 0
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCResultSet.checkColumn(Unknown Source)
    at org.hsqldb.jdbc.JDBCResultSet.getColumnInType(Unknown Source)
    at org.hsqldb.jdbc.JDBCResultSet.getInt(Unknown Source)
    at net.ucanaccess.jdbc.UcanaccessResultSet.getInt(UcanaccessResultSet.java:445)
    ... 2 more
Caused by: org.hsqldb.HsqlException: Column not found: 0
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    ... 7 more
```

Code:


```
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class DBConnection {
    
    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;
    
    // 1. Schritt: Oracle JDBC Treiber laden
    
    public static void holDbDaten() {
        
//        Connection connection = null;
//        Statement statement = null;
//        ResultSet resultSet = null;
        
        try {
            Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
        }
        catch (ClassNotFoundException cnfex) {
            
            System.out.println("Problem beim laden des Datenbanktreibers!");
            cnfex.printStackTrace();
        }
        
        
        // 2. Schritt: Öffnen der Datenbank Verbindung
        
        try {
            String msAccDB = "D:"
                    + "/Test.accdb";
            String dbURL = "jdbc:ucanaccess://" + msAccDB;
            
            
            // Step 2.A: Create and 
            // get connection using DriverManager class
            connection = DriverManager.getConnection(dbURL); 

            // Step 2.B: Creating JDBC Statement 
            statement = connection.createStatement();
 
            // Step 2.C: Executing SQL and 
            // retrieve data into ResultSet
            
            int[] kostenstellen = {22854, 24350, 24351, 24352, 24550, 24820, 25330, 26389, 26390, 26391, 26392, 26393, 27139, 27450, 28411, 28470, 28490, 63450, 63500, 63600, 63700, 63800};
//            int[] errechneteSumme = new int[21];

            

            
//            for (int stelle : Summen) {
            
                for (int i = 0; i < kostenstellen.length; i++) {
              
                resultSet = statement.executeQuery("SELECT Betrag FROM Kostenjournal WHERE KstStNr = " + kostenstellen[i]);
  //                      + " (SELECT SUM (Betrag) FROM Kostenjournal WHERE KstArtNr"
  //                      + " = 621100)");
  //              + " = 621100 AND 624100 AND 624200 AND 624300 AND 624400)");
            

            }

           
            // processing returned data and printing into console
            while(resultSet.next()) {
                int z = 1;
                System.out.print(z + ". Summe: ");
                z++;
                System.out.println(resultSet.getInt(0));
                

            }    

        }
        catch(SQLException sqlex){
            sqlex.printStackTrace();
        }
        
        finally {
            // Step 3: Closing database connection
            try {
                if(null != connection) {
                    // cleanup resources, once after processing
                    resultSet.close();
                    statement.close();
 
                    // and then finally close connection
                    connection.close();
                }
            }
            catch (SQLException sqlex) {
                sqlex.printStackTrace();
            }
        } 
    }
}
```


----------



## Thallius (13. Aug 2019)

probier es mal mit

getInt("Betrag");

und keine Ahnung von Access aber da gibt es bestimmt auch sowas wie ein IN bei sql

Gruß

Claus


----------



## Genkin (13. Aug 2019)

Du meinst, in der while Schleife? Bringt nix. Wenn ich z.B. die erste Zahl aus dem int[] nehme, dann ändert sich die Meldung von "0" in die erste Zahl..


----------



## Thallius (13. Aug 2019)

Hae?


----------



## M.L. (13. Aug 2019)

> Du meinst, in der while Schleife?


Damit ist wohl eher der Befehl "
System.out.println(resultSet.getInt(0)); " gemeint:   "Betrag" statt 0  (vgl. z.B. mit http://www.java2s.com/Code/JavaAPI/java.sql/ResultSetgetIntintcolumnIndex.htm
Und Access hat einen IN-Operator:  https://docs.microsoft.com/en-us/of...iscellaneous/in-operator-microsoft-access-sql


----------



## Genkin (14. Aug 2019)

Danke, dass mit "Betrag" und IN hat hervorragend geklappt.

Nun zu meinem nächsten Problem. Bevor diese Daten in die DB kommen, will ich sie importieren (liegen als CSV vor). Der Import an sich klappt, nur es wird 9x dieselbe Zeile eingetragen...

Hier der Code:


```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class CsvIntoDb extends DBConnection {


public static void load() throws IOException, ClassNotFoundException, SQLException {
    String sql = " INSERT INTO Kostenjournal (AbrKr, AbrJahr, AbrMon, KstStNr, KstStBez, KstArtNr, KstArtBez, Std, Betrag) VALUES(?,?,?,?,?,?,?,?,?) ";


    try {
            BufferedReader bReader = new BufferedReader(new FileReader("D:\\csv.csv"));
            String line = "";
            while ((line = bReader.readLine()) != null) {
                try {

                    if (line != null)
                    {
                       
                        String[] array = line.split(";+");
                        for(String result:array)
                        {
                            System.out.println(result);
                           
     //Create preparedStatement here and set them and excute them
                           
                            preparedStatement = connection.prepareStatement(sql);
                            preparedStatement.setString(1, array[0]);  
                            preparedStatement.setString(2, array[1]);
                            preparedStatement.setString(3, array[2]);
                            preparedStatement.setString(4, array[3]);
                            preparedStatement.setString(5, array[4]);
                            preparedStatement.setString(6, array[5]);
                            preparedStatement.setString(7, array[6]);
                            preparedStatement.setString(8, array[7]);
                            preparedStatement.setString(9, array[8]);

                                                                   
                            preparedStatement.executeUpdate();
                            preparedStatement.close();
                           
       //Assuming that your line from file after split will folllow that sequence

                        }
                    }
                }
                finally
                {
                   if (bReader == null)
                    {
                        bReader.close();
                    }
                }
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}
```


Irgendwas hab ich da verkehrt gemacht, weiß nur nicht was


----------



## mihe7 (14. Aug 2019)

Genkin hat gesagt.:


> Irgendwas hab ich da verkehrt gemacht, weiß nur nicht was


Naja, Du iterierst über das Array und fügst somit für jede Spalte Deine setStrings aus: macht 9 Stück.

Probiers mal so:


```
public static void load() throws IOException, SQLException {
    String sql = " INSERT INTO Kostenjournal (AbrKr, AbrJahr, AbrMon, KstStNr, KstStBez, KstArtNr, KstArtBez, Std, Betrag) VALUES(?,?,?,?,?,?,?,?,?) ";

    try(PreparedStatement stmt = connection.prepareStatement(sql);
            BufferedReader bReader = new BufferedReader(new FileReader("D:\\csv.csv"))) {
        String line;
        while ((line = bReader.readLine()) != null) {
            String[] array = line.split(";+");
            for (int i = 0; i < array.length; i++) {
                stmt.setString(i+1, array[i]);
            }
            stmt.addBatch();
        }
        stmt.executeBatch();
    }
}
```
EDIT: noch ein paar Korrekturen am Code vorgenommen.


----------



## Genkin (15. Aug 2019)

Guten Morgen

Vielen Dank! Das passt super.

Die erste Zeile enthält Spaltennamen, welche ich bereits in der DB selber übernommen habe. Wie kann ich den Algorithmus so anpassen, dass er in der zweiten Zeile beginnen soll?


----------



## mrBrown (15. Aug 2019)

Na die erste Zeile einfach ignorieren, z.B. entweder mit ner Bedingung in der Schleife oder aus der Schleife zeihen.


----------



## mihe7 (15. Aug 2019)

Ja, wenn Du weißt, dass die Datei immer wenigstens einen Header hat, dann füg einfach `bReader.readLine();` vor der Schleife ein.


----------



## Genkin (15. Aug 2019)

mihe7 hat gesagt.:


> Ja, wenn Du weißt, dass die Datei immer wenigstens einen Header hat, dann füg einfach `bReader.readLine();` vor der Schleife ein.



Dankeschön.

Ich habe jetzt ein anderes Problem.
Die CSV Datei enthält int und String Daten. In meinem Code habe ich ja die String[] array zum lesen stehen.
Wenn ich die Spalten in der DB als Text einstelle, klappt das importieren. Aber so kann ich ja nicht mit den Zahlen arbeiten, wenn die als Text in der DB eingespeichert sind. Wenn ich die Spalten in der DB passend zu der einzulesenden csv einstelle, dann klappt der import nicht. Es kommt dann folgende Fehlermeldung:


```
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::4.0.1 data exception: invalid character value for cast
    at net.ucanaccess.jdbc.UcanaccessPreparedStatement.setString(UcanaccessPreparedStatement.java:701)
    at CsvIntoDb.load(CsvIntoDb.java:23)
    at GUI$2.actionPerformed(GUI.java:62)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.sql.SQLDataException: data exception: invalid character value for cast
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.throwError(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.setParameter(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.setString(Unknown Source)
    at net.ucanaccess.jdbc.UcanaccessPreparedStatement.setString(UcanaccessPreparedStatement.java:699)
    ... 38 more
Caused by: org.hsqldb.HsqlException: data exception: invalid character value for cast
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.Scanner.convertToNumber(Unknown Source)
    at org.hsqldb.types.NumberType.convertToType(Unknown Source)
    ... 41 more
```


Ich hatte mir dann überlegt, die DB Spalten als String stehen zu lassen und dann noch eine zusätzliche Klasse zu erstellen, in der ich die Datentypen in der DB caste bzw. konvertiere... was aber nicht funktioniert.


```
import java.sql.SQLException;

import javax.swing.JOptionPane;

public class Converter extends DBConnection {
   
    public static void convert() {
       
        try {
//            resultSet = statement.executeQuery("SELECT CAST((AbrKr, AbrJahr, AbrMon, KstStNr, KstArtNr, Std, Betrag) AS INT) FROM Kostenjournal");
            resultSet = statement.executeQuery("SELECT CONVERT(int(10), Betrag)) FROM Kostenjournal");
           
// Syntax:        SELECT CONVERT(varchar(10), field_name) FROM table_name
           
            JOptionPane.showMessageDialog(null, "CASTEN erfolgreich!");
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            JOptionPane.showMessageDialog(null, "CASTEN nicht erfolgreich!");
            e.printStackTrace();
        } finally {
            try {
                resultSet.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "Fehler beim schließen des RESULTSET in der Klasse Converter!");
            }
        }
       
       
    }

}
```

Für das unausgeklammerte ResultSet (da wollte ich probehalber nur eine Spalte umwandeln) im Code hier drüber kommt dann diese Fehlermeldung:

```
UCAExc:::4.0.1 type not found or user lacks privilege: BETRAG
```
Für den ausgeklammerten resultSet kommt:

```
UCAExc:::4.0.1 java.lang.NullPointerException java.lang.NullPointerException
```


----------



## mihe7 (15. Aug 2019)

Genkin hat gesagt.:


> Aber so kann ich ja nicht mit den Zahlen arbeiten, wenn die als Text in der DB eingespeichert sind. Wenn ich die Spalten in der DB passend zu der einzulesenden csv einstelle, dann klappt der import nicht. Es kommt dann folgende Fehlermeldung:


Das sollte eigentlich nicht sein. Wenn Du per setString eine Zeichenkette angibst, die eine Zahl enthält, dann sollte das automatisch umgewandelt werden. 

Das scheint auch versucht zu werden:


Genkin hat gesagt.:


> Caused by: java.sql.SQLDataException: data exception: invalid character value for cast


Kann es sein, dass die Reihenfolge der eingelesenen Spalten mit denen der importierten nicht zusammenpasst und somit eine ganz andere Zeichenkette auf eine int-Spalte abgebildet wird?


----------



## Genkin (15. Aug 2019)

mihe7 hat gesagt.:


> Das sollte eigentlich nicht sein. Wenn Du per setString eine Zeichenkette angibst, die eine Zahl enthält, dann sollte das automatisch umgewandelt werden.
> 
> Das scheint auch versucht zu werden:
> 
> Kann es sein, dass die Reihenfolge der eingelesenen Spalten mit denen der importierten nicht zusammenpasst und somit eine ganz andere Zeichenkette auf eine int-Spalte abgebildet wird?



Habe es grade nochmal geprüft, passt eig..

CSV:       Zahl | Zahl | Zahl | Zahl | Text | Zahl | Text | Zahl | Zahl
DB:        Zahl | Zahl | Zahl | Zahl | Text | Zahl | Text | Zahl | Zahl

Wobei mir grade aufgefallen ist, dass die letzte Stelle in der CSV eine Währung bzw. Gleitkommazahl ist.. in der DB hab ich die dazugehörige Spalte aber nur als INT deklariert. Hab grad mal als Währung versucht da es auch tatsächlich eine Währung darstellt, aber es kommt dieselbe Fehlermeldung.


EDIT: 

In der Klasse "Berechne" greife ich nämlich auf die Beträge (letzte Spalte) zu mit 

```
resultSet = statement.executeQuery("SELECT SUM (Betrag) FROM Kostenjournal WHERE KstStNr IN (" + kostenstellen[i] + ")"
                  + "AND KstArtNr IN (621100, 624100, 624200, 624300, 624400)");
```

Ich führe zuerst den Import durch, was an sich klappt (wenn ich die Klasse Converter nicht aufrufe), aber wenn ich dann die Klasse Berechne aufrufe, kommt eben auch diese Fehlermeldung:

```
UCAExc:::4.0.1 incompatible data type in operation
```

Die Klasse Berechner funktioniert. Das habe ich geprüft gehabt, in dem ich die CSV manuel in die DB eingepflegt hatte. Da waren dann aber auch die Spaltentypen richtig. Hier habe ich jetzt ja alle Spaltentypen auf String stehen. Deswegen rechnet er ja auch nicht. Daher wollte ich halt die Spaltentypen nach dem Import casten/konvertieren...


----------



## mihe7 (15. Aug 2019)

Genkin hat gesagt.:


> Ich führe zuerst den Import durch, was an sich klappt (wenn ich die Klasse Converter nicht aufrufe)


Heißt: die Werte stehen korrekt in der DB.



Genkin hat gesagt.:


> aber wenn ich dann die Klasse Berechne aufrufe, kommt eben auch diese Fehlermeldung:


Dann musst Du Dich langsam rantasten. Probier erstmal ohne WHERE-Klausel.


----------



## Genkin (16. Aug 2019)

Guten Morgen
Habe ich probiert, es kommt dieselbe Fehlermeldung.

Aber wieso klappt das casten denn nicht..? Die Datentypen müssen geändert werden..


----------



## kneitzel (16. Aug 2019)

Zu #11 noch einmal:

Also ich weiß nicht so recht: Du hast ja eine Access Datenbank unter drunter. Da ist eine erste Frage, ob er so Dinge wie CONVERT überhaupt so kennt. Evtl. sieht die Funktion anders aus oder eben eine andere Funktion müsste benutzt werden. CInt und so kennt Access meiner Meinung nach. Aber ob das rein VB ist oder auch in die Datenbankabfragen rein läuft, das kann ich nicht sagen.

"Type not found: BETRAG" (verkürzt dargestellt) scheint zu bedeuten, dass er da Dein BETRAG als Typ angesehen hat...
Aber die Abfrage ist auch nicht stimmig: SELECT CONVERT(int(10), Betrag)) FROM Kostenjournal
2x "(", 3x ")" - so kann es nicht klappen....
Die Cast Anweisung mit mehreren Feldern kommt mir auch etwas dubios vor. Da hätte ich pro Feld ein Cast erwartet....


----------



## Genkin (16. Aug 2019)

Hast Recht, sowas wie "SELECT CONVERT(int(10), Betrag)) FROM Kostenjournal " funktioniert nicht. Es muss so eine Syntax sein:

 ALTER TABLE table_name
 ALTER COLUMN column_name datatype

So funktioniert es auch für alle Spalten! Nur eine nicht  nämlich für die letzte, Betrag...

Betrag ist z.B. 806,03...
Das kann man so ohne weiteres nicht von einem String in einen integer umwandeln, weil das Komma dort zu diesen Fehlern führt!
Habe es mit decimal, currency, money versucht, gehen alle nicht


----------



## Thallius (16. Aug 2019)

wie wärs mit float?


----------



## kneitzel (16. Aug 2019)

Oder evtl. einmal das "," durch "." ersetzen und dann probieren.


----------



## Genkin (16. Aug 2019)

kneitzel hat gesagt.:


> Oder evtl. einmal das "," durch "." ersetzen und dann probieren.



Dann wandeln sich manche Beträge in der CSV in ein Datum um..
Float klappt auch nicht leider. "25,6" wird dann zu 25.Jun


```
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::4.0.1 data exception: invalid character value for cast in statement [ALTER TABLE Kostenjournal
ALTER COLUMN Betrag float]
```


----------



## mihe7 (16. Aug 2019)

Genkin hat gesagt.:


> Dann wandeln sich manche Beträge in der CSV in ein Datum um..


?!?


----------



## kneitzel (16. Aug 2019)

Es geht ja erst einmal um die Access Datenbank und um die Umwandlung der Datentypen.

Bei Fließkommazahlen ist der . nun einmal oft der Trenner. So er mit dem Trenner , nicht klar kommt, kann es also ein Weg sein:
a) In den Strings (die Du derzeit als Datentyp in dem Column zu haben scheinst - so habe ich dich zumindest verstanden) die "," durch "." ersetzen.
b) Dann wird der Datentyp umgesetzt, so dass in der spalte nur noch Fließkommazahlen stehen

Da spielt es erst einmal keine Rolle, was Excel anzeigt, wenn Du ein CSV Export in Excel öffnest. Das ist ja nur eine Darstellung in Excel! Markier die Spalte und setz als Typ, dass es eine Zeichenkette sein soll und schon wird ein 25.7 nicht mehr als Datum angezeigt. Aber wie gesagt: Das hat auch absolut nichts mit den Daten in der Datenbank zu tun!


----------



## Genkin (16. Aug 2019)

kneitzel hat gesagt.:


> Es geht ja erst einmal um die Access Datenbank und um die Umwandlung der Datentypen.
> 
> Bei Fließkommazahlen ist der . nun einmal oft der Trenner. So er mit dem Trenner , nicht klar kommt, kann es also ein Weg sein:
> a) In den Strings (die Du derzeit als Datentyp in dem Column zu haben scheinst - so habe ich dich zumindest verstanden) die "," durch "." ersetzen.
> ...



Okaay habe dich verstanden.
Ich habs jetzt auch hinbekommen, undzwar hiermit:


```
String replacer = "UPDATE Kostenjournal SET Betrag = REPLACE(Betrag, ',', '.');";
            preparedStatement = connection.prepareStatement(replacer);
            preparedStatement.execute();
            

            resultSet = statement.executeQuery("ALTER TABLE Kostenjournal\r\n" + 
                    "ALTER COLUMN Betrag float;");
```

Die Spalte in der DB wurde jetzt angepasst mit ".". Berechnen tut er jetzt auch alles 

Jetzt muss ich das ganze noch in eine bestehende Excel in die jeweiligen Zellen schreiben. Dafür hab ich aber schon ein neues Thema auf. Ich danke euch rechtherzlich


----------

