# prepared statement



## seven11 (23. Okt 2006)

Hallo Leute,

ich versuche durch ein prepared statement eine Tabelle in meiner mySQL Datenbank zu befüllen. Hier ist mal der Code:

```
public void insertIntoVS_Vehicle_Import (String db_gfz, String db_fahrgestellnummer,String db_marke_id, 
			String db_karosserie_id,String db_klasse_id, String db_typ, String db_haendler_id, String db_kraftstoff_id,
			String db_emission, String db_verbrauch, String db_getriebe_id, String db_kw, String db_km, 
			String db_preis) throws SQLException {
		PreparedStatement stmt = con.prepareStatement ("INSERT INTO vs_vehicle_import " +
				"(db_gfz, db_fahrgestellnummer, db_marke_id, " +
				"db_karosserie_id, db_klasse_id, db_typ, db_haendler_id, db_kraftstoff_id, db_emission, db_verbrauch" +
				"db_getriebe_id, db_kw, db_km, db_preis) VALUES (?,?,?,?" +
				"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?" +
				"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?" +
				"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?" +
				"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
		
		
			stmt.setString (1, db_gfz );
			stmt.setString (2, db_fahrgestellnummer );
			stmt.setString (3, db_marke_id );
			stmt.setString(4, db_karosserie_id);
			stmt.setString(5, db_klasse_id);
			stmt.setString(6,  db_typ);
			stmt.setString(7, db_haendler_id);
			stmt.setString(8, db_kraftstoff_id);
			stmt.setString(9, db_emission);
			stmt.setString(10, db_verbrauch);
			stmt.setString(11, db_getriebe_id);
			stmt.setString(12, db_kw);
			stmt.setString(13, db_km);
			stmt.setString(14, db_preis);
			stmt.setString(15, "test");
			stmt.setString(16, "test");
			stmt.setString(17, "test");
			stmt.setString(18, "test");
			stmt.setString(19, "test");
			stmt.setString(20, "test");
			stmt.setString(21, "test");
			stmt.setString(22, "test");
			stmt.setString(23, "test");
			stmt.setString(24, "test");
			stmt.setString(25, "test");
			stmt.setString(26, "test");
			stmt.setString(27, "test");
			stmt.setString(28, "test");
			stmt.setString(29, "test");
			stmt.setString(30, "test");
			stmt.setString(31, "test");
			stmt.setString(32, "test");
			stmt.setString(33, "test");
			stmt.setString(34, "test");
			stmt.setString(35, "test");
			stmt.setString(36, "test");
			stmt.setString(37, "test");
			stmt.setString(38, "test");
			stmt.setString(39, "test");
			stmt.setString(40, "test");
			stmt.setString(41, "test");
			stmt.setString(42, "test");
			stmt.setString(43, "test");
			stmt.setString(44, "test");
			stmt.setString(45, "test");
			stmt.setString(46, "test");
			stmt.setString(47, "test");
			stmt.setString(48, "test");
			stmt.setString(49, "test");
			stmt.setString(50, "test");
			stmt.setString(51, "test");
			stmt.setString(52, "test");
			stmt.setString(53, "test");
			stmt.setString(54, "test");
			stmt.setString(55, "test");
			stmt.setString(56, "test");
			stmt.setString(57, "test");
			stmt.setString(58, "test");
			stmt.setString(59, "test");
			stmt.setString(60, "test");
			stmt.setString(61, "test");
			stmt.setString(62, "test");
			stmt.setString(63, "test");
			stmt.setString(64, "test");
			stmt.setString(65, "test");
			stmt.setString(66, "test");
			stmt.setString(67, "test");
			stmt.setString(68, "test");
			stmt.setString(69, "test");
			stmt.setString(70, "test");
			stmt.setString(71, "test");
			stmt.setString(72, "test");
			stmt.setString(73, "test");
			stmt.setString(74, "test");
			stmt.setString(75, "test");
			stmt.setString(76, "test");
			stmt.setString(77, "test");
			stmt.setString(78, "test");
			stmt.setString(79, "test");
			stmt.setString(80, "test");
			stmt.setString(81, "test");
			stmt.setString(82, "test");
			stmt.setString(83, "test");
			stmt.setString(84, "test");
			stmt.setString(85, "test");
			stmt.setString(86, "test");
			stmt.setString(87, "test");
			stmt.setString(88, "test");
stmt.executeUpdate();
		
		stmt.close();
		System.out.println ("erfolgreich eingefuegt!");
	}
	public void releaseConnection() throws SQLException
	{
		con.close();
	}
```

Überall wo jetzt noch "Test" steht, werde ich später weitere Variablen zuweisen. Für meine Testzwecke habe ich das mal so gelassen. Nun rufe ich das ganze so auf:

```
String db_gfz = ...; //hier ist natürlich immer ein wert zugewiesen
String db_fahrgestellnummer = ...;
...
String url = "jdbc:mysql://localhost:3306/prod_client_testDB";
					String user = "root";
					String passwd = "";
					PTDBFill ref = new PTDBFill();
					ref.connect (url, user, passwd);
					ref.insertIntoVS_Vehicle_Import (db_gfz, db_fahrgestellnummer, db_marke_id, db_karosserie_id, db_klasse_id, db_typ, db_haendler_id, db_kraftstoff_id, db_emission, db_verbrauch, db_getriebe_id, db_kw, db_km, db_preis);
					ref.releaseConnection();
```
eigentlich müßte das ja so funktionieren. Ich weiß nicht warum ich die Fehlermeldung "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null,'CROSSFIRE ROADST','21465',null,'0','0,00','2','160','0026','00025990','tes' at line 1" erhalte. Vielleicht könnt ihr mir helfen. Ist die Anzahl der Values nicht korrekt? Oder stimmt tatsächlich was an der Syntax nicht? Danke...


----------



## seven11 (23. Okt 2006)

Hallo Leute,

ich komm immer noch nicht dahinter.
Vielleicht ist das ja auch ziemlich unpraktisch wie ich das ganze versuche zu lösen?
Wäre für jede Hilfe dankbar...


----------



## foobar (23. Okt 2006)

Lass dir mal die Query auf STDOUT ausgeben bevor du sie abfeuerst.
Der Code an sich ist aber etwas merkwürdig.

- Warum übergibst du IDs als String?
- Du könntest dir das Leben etwas erleichtern, wenn du der  Methode eine bean übergibst, die alle Daten kapselt. Ansonsten hast du schnell mal einen Dreher beim Aufruf.
- Eine Tabelle mit 88 Spalten? Muß das so sein?


----------



## seven11 (23. Okt 2006)

Hallo,

ich weiß leider nicht wie du das mit der bean meinst (vielleicht erklärst du mir das?). Das mit der Spaltenanzahl muß leider sein! Habe aus den Ids Interger gemacht. Ich hatte sie als String weil ich sie davor aus einer csv Datei ausgelesen habe. Jetzt packe ich die Daten in eine Tabelle.


```
ref.insertIntoVS_Vehicle_Import (db_gfz, db_fahrgestellnummer, db_marke_id, Integer.parseInt(db_karosserie_id), Integer.parseInt(db_klasse_id), db_typ, Integer.parseInt(db_haendler_id), db_foto, Integer.parseInt(db_kraftstoff_id), db_emission, db_verbrauch,Integer.parseInt(db_getriebe_id), Float.parseFloat(db_kw), Integer.parseInt(db_km), Float.parseFloat(db_preis), Float.parseFloat(db_aktionspreis),db_farbe_id, Integer.parseInt(db_farbe_kategorie_id)....
```
dürfte doch ok sein?
Darf z.B. der Wert db_getriebe_id in Integer.parseInt(db_getriebe_id) null sein? Wahrscheinlich nicht oder?
Auf alle Fälle bekomme ich eine fehlermeldung:
Connect erfolgreich!
java.lang.NumberFormatException: null
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)


----------



## KSG9|sebastian (23. Okt 2006)

Jetzt erklär mal warum 88 Spalten notwendig sind?
Ist das ne Vorgabe (wenn ja dann hau deinen Chef/den DB Designer), wenn nicht: Überdenk das nochmal. Schau dir Normalisierung an.


----------



## SlaterB (23. Okt 2006)

ganz egal wie die Vorgaben sind,
zum Programmieren lernen/ ersten testen nimm eine Tabelle mit einem oder später 5 Attribute,

so macht dein Code keinen Sinn, niemand will das alles anschauen,

parseInt funktioniert mit null nicht, richtig
statt einer Zeile mit lauter parseInt mache lieber die Berechnung in einzelnen Zeilen vorher,
dann weißt du an welcher Stelle dein Fehler auftritt, falls du die Zeilennummer hast

bei 'Insert Into' muss die Anzahl der Attributnamen und Values übereinstimmen,
wenn du alle Felder befüllen willst, dann mache direkt 'Insert Into Tabelle Values (..)'


und editiere bitte deine Code-Postings falls du noch weiter fragst,
paar Zeilenumbrüche in die langen Zeilen..
(edit: geht wohl nicht da anonym gepostet? )


----------



## prepared statement (23. Okt 2006)

das ist eigentlich die größte Tabelle von allen. Mein Chef meint daß er die so bekommen hat. Und das soll auch so bleiben. Macht keinen Sinn mehr da was zu schrauben meint er...
Wie auch immer, da muß ich jetzt eine Lösung finden. Und vielleicht habt hr ja Tips wie es am besten geht?
Habe schon vieles gesucht, aber mich nicht wirklich entscheiden können.
Vielleicht ist ja cachedRowSet oder updateableResultSet eine bessere Lösung?


----------



## SlaterB (23. Okt 2006)

was ist denn überhaupt dein Problem?

was spricht gegen PreparedStatement?
NullPointerException liegt am parseInt,
das die Anzahl der Values falsch ist habe ich auch schon gesagt,

was geht noch nicht?


----------



## seven11 (23. Okt 2006)

eigentlich nur, daß der Code so unübersichtlich ist und die ganzen Spaltennamen so übergeben werden.
Bei einer kleinen Änderung müßte ich die ganzen Namen durchgehen.
Und ich möchte mir die Möglichkeit offen lassen einige Spalten nicht eintragen zu müssen.
Sorry wenn ich dich auf die Palme bringe aber du mußt doch auch zugeben daß das so kein schöner Programmierstil ist oder. Wollte nur wissen wie ihr das besser und schöner lösen würdet? Habe damit leider weniger Erfahrung...
Danke!


----------



## SlaterB (23. Okt 2006)

läßt mich völlig kalt, keine Sorge 
nur bringt es dir nix, ungenaue Fragen zu stellen,

du hast also kein Problem mehr mit der Anfrage,
sondern nur noch mit dem Handling sovieler Attribute,
gut zu wissen,

mit reinem JDBC kommt man da erstmal nicht weiter,
da musst du explizit angeben welche Spalten welche Werte bekommen,

du kannst dir natürlich etwas generisches höheres schreiben, irgendeine eigene Klasse mit set- + get für alle Attribute,
evtl. mit einem Array aller Spaltennamen und set- + get- indexmäßig von 0-88,

wäre ein größerer Aufwand, 
aber danach könntest du dann Anfragen einfacher zusammenschrauben,
bei deinen bisherigen Fragen klingts du dem aber nicht ganz gewachsen, daher vorsichtig rangehen,

solche höhere DB-Frameworks gibts natürlich auch schon in der Welt, 
Hibernate z.B., aber auch wieder schwierig zu konfigurieren..


----------



## seven11 (24. Okt 2006)

Hallo,

ich habe mich jetzt entschieden meine Tabelle mit dem "Updatable Result Set" zu bearbeiten. Scheint mir irgendwie kompakter und einfacher für meinen Fall (persönliche Meinung). Nun habe ich 2 Methoden geschrieben, die das durchführen. Die eine Methode soll nur ein insertRow() machen und die andere soll eine Zeile updaten. Nur möchte ich vorher eine Abfrage durchführen, die nur dann eine Zeile updaten soll falls die "Werte des eindeutigen Schlüssels" gleich sind. Ansonsten soll sie die Zeile an die Tabelle anfügen. Hier sind nun meine zwei Methoden:


```
public void insertDB()throws SQLException{
		 
        // ein updatable result set
        Statement stmt = con.createStatement(
            ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        ResultSet resultSet = stmt.executeQuery("SELECT * FROM vs_vehicle_import");
    
        // cursor zur Stelle bewegen die ich updaten will
        resultSet.last();     //ich glaub es geht auch ohne diese Zeile
    
        // inserte die Werte der Spalten in dieser Zeile
        resultSet.moveToInsertRow();
        resultSet.updateString("db_gfz", "blabla");
        resultSet.updateString("db_fahrgestellnummer", "blabla");
        resultSet.updateString("db_marke_id", "12");
                
        
       //  Insert the row; if auto-commit is enabled, insert is committed
        resultSet.insertRow();
        stmt.close();
        System.out.println ("erfolgreich eingefuegt!");
        
    }
```

und hier ist die updateMethode:

```
public void updateDB()throws SQLException{
	 
        //  updatable result set
        Statement stmt = con.createStatement(
            ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        ResultSet resultSet = stmt.executeQuery("SELECT * FROM vs_vehicle_import");
    
        // cursor zur Zeile die geupdated werden soll
        resultSet.first();
    
        //  inserte die Werte der Spalten in dieser Zeile
        resultSet.updateString("db_gfz", "test");
        resultSet.updateInt("db_klasse_id", 2);
        ...
        
       //  Update the row; if auto-commit is enabled, update is committed
        resultSet.updateRow();
        stmt.close();
        System.out.println ("erfolgreich eingefuegt!");
        
    }
```

So, nun mein Problem. Wie stelle ich es am besten an das er mir schon vorhandene Zeilen anhand des Primarykey rausfindet und dann bei den nötigen Spaltenwerten ein update macht? Ist diese Zeile eine neue soll er nur ein insert machen. Bis jetzt habe ich gedacht, ich mache vor dem Aufruf dieser Methoden eine Abfrage auf den Primarykey, falls identisch führe ein update durch, falls nicht mache ein insert (nur wie sieht das in der Ausführung aus?). Später muß ich wohl noch in meiner updateDB() Methode jeden einzelnen Spaltenwert überprüfen und nur bei veränderten Werten ein update durchführen (vielleicht ist es aber auch einfacher die ganze Zeile ganz upzudaten)?


----------

