# Verständnisfrage



## Manuela (29. Aug 2008)

Hallo, ich habe ein Serverprogramm geschrieben das unter anderem auch Daten in eine Mysql Datenbank schreibt.
da mehrere Tabellen bei einer Insert bedient werden müßen benutze ich unten stehenden Code
kann ich das irgendwie vereinfachen weil ich befürchte das je größer die Tabelle wird um so länger wird die Verarbeitungszeit.

Beispiel: Ich habe Material das bestellt werden muß. Dafür habe ich eine Tabelle in dem die Daten sind, und eine Tabelle in der die Bestellungen eingetragen werden, und das ich die Daten wenn die bestellung eintrifft auch zuordnen kann benutze ich die autoincrement Spalte der Tabelle "bestand". 
über ein Insert <Daten> in die Teile Tabelle und dann die Laufende Nr dieser Tabelle (LaufNr) benutze ich 
um einen Insert <Bestelltabelle> mit der (LaufNr)  zu finden.



```
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
stmt.execute("INSERT INTO bestand (...) values(...) );  // hier befürchte ich das es immer länger dauert je mehr 
Datensätze in der Tabelle sind.
res = stmt.executeQuery("Select * FROM bestand order by LaufNr");
res.last();
int NR=res.getInt(1);
res.close();
stmt.execute("INSERT INTO bestell(<laufende nr von bestand>,...) values(NR,...));
```

ist meine Furcht unbegründet oder gibt es eine andere art dies zu bewerkstelligen.

das Serverprogramm bedient so ca 35 Clients 
und da kommen schon eine menge Daten zusammen.

Gruß Manuela


----------



## musiKk (29. Aug 2008)

Ein Insert ist nicht so kritisch. Kritisch ist das Select, welches diesem folgt, da ein "order by" vor allem bei grossen Tabellen enorm teuer ist. Wenn du an das autoincrement kommen willst, dann probiere mal Statement.getGeneratedKeys(), aber ich habe gelesen, dass in Abhaengigkeit vom Treiber das nicht immer funktioniert. Da du hier schon viele Daten hast und die Performance leiden kann, solltest du ueber eine Datenbank-Funktion nachdenken, die den Insert uebernimmt und dir das autoincrement zurueckliefert, so dass du die z. B. folgendermassen aufrufen kannst:

```
SELECT insertBestandsdaten(...) as newId
```
Wenn diese ID jedoch nur fuer die Bestell-Tabelle benoetigt wird und im Java-Programm irrelevant ist (wie es mit IDs meistens sein sollte), dann kann das die Funktion auch gleich noch machen.
Natuerlich geht damit die Unabhaengigkeit der Datenbank ein wenig zurueck, aber hier sollte sich der Aufwand in Grenzen halten.


----------



## Manuela (29. Aug 2008)

Hallo wie wäre es mit so was,
was noch zu bedenken ist, weil so viele clients arbeiten, muß ich auschliessen können das 
es zu einem Datensalat kommen kann.

mit lock will ich nicht unbedingt die sache machen.
reicht da dieser mechanismus aus, das auch der tatsächlichen datensatz geliefert wird.



```
//  ALT  

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); 
stmt.execute("INSERT INTO bestand (...) values(...) );  // hier befürchte ich das es immer länger dauert je mehr 
Datensätze in der Tabelle sind. 
res = stmt.executeQuery("Select * FROM bestand order by LaufNr"); // hier ist natürlich das problem
res.last(); 
int NR=res.getInt(1); 
res.close(); 
stmt.execute("INSERT INTO bestell(<laufende nr von bestand>,...) values(NR,...)); 


// neu

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); 
stmt.execute("INSERT INTO bestand (...) values(...) ); 
res = stmt.executeQuery("Select LAST_INSERT_ID()); // Der liefert mir die Richtige ID
// aber ist das auch sicher dass das auch die richtige ist (die zu dem Insert passt ???) 
res.last(); 
int NR= 0;
if(res.next()){
   NR=res.getInt(1); 
}
res.close(); 
stmt.execute("INSERT INTO bestell(<laufende nr von bestand>,...) values(NR,...));
```


Gruß Manuela


----------



## Manuela (31. Aug 2008)

Kann mir denn keiner eine verlässliche Antwort geben,
ob das ausreicht um keinen Datensalat zu bekommen

Gruß Manuela


----------



## musiKk (31. Aug 2008)

Ich bin mir da nicht hundertprozentig sicher, vor allem, weil ich auch die Funktion last_insert_id() nicht kenne. An und fuer sich sollte das, was du da hast, eine Transaktion sein, die erst mit dem Schliessen der Verbindung oder einem commit abgeschlossen wird. Alles davor muesste atomar und damit konsistent sein. Aber wie gesagt, ich bin mir nicht komplett sicher.

_edit_: Hab nun doch mal geguglt: Siehe das Handbuch: _For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a non-magic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed._
Es ist demnach also sicher.


----------

