Frage von klugshicer, 62

MySQL: Wie bekommt man den Wert eines Primärschlüssels (autoincrement) von einem Datensatz der gerade neu erstellt wurde?

Wenn ich ein Querry für ein "Insert" absetze und der Primärschlüssel auf Autoincrement gestetzt ist dann übergebe ich ja keinen Wert für den Primärschlüsse.

Aber wenn ich direkt im Anschluss an das Insert die ID des Datensatzes benötige, wie komme ich dann an den Wert des Primär-Schlüssels

Antwort
von RakonDark, 27

Es gibt eine ATOM FUNKTION die bei einem INSERT  die ID angiebt .

LAST_INSERT_ID .

Da man mit einem Insert auch mehrere Datensätze gleichzeitg eintragen kann , wird dann der letzte Datensatzeintrag als LAST_INSERT_ID genommen .

ATOM funktion meint, das zwischen dem Eintrag und dem ermitteln kein anderer Befehl ausgeführt wird .

Wenn aber mehrer INSERTS folgen , kann dieser Wert schon wieder nicht der letzte Datensatz sein . Dann könnte man höchstens die Tabelle sperren und den AUTOINCREMENT wert auslesen .

Im allgemeinen bringt es aber nichts, deswegen ist es ja ein AUTO Wert , da kümmert sich die Datenbank drumm . Es geht also nur mit Sperrung der Tabelle um wirklich zu wissen was zu diesem Zeitpunkt die letzte ID ist.

Diese ID ist aber dann im folgenden vielleicht schon veraltet , also müsste die Tabelle solange gesperrt sein bis der Wert verarbeitet wurde .

Man kann also eigentlich nicht wirklich was mit SELECT  letzte id Anfangen ohne die Tabelle sperren zu müssen . Die denke ist halt eher ein Architektur Fehler in der Denke  und wird schnell wieder verworfen und durch workarounds kompensiert.



Kommentar von RakonDark ,

Mann sollte auch noch sagen , das aus performance gründen der SELECT meist vor dem INSERT stadtfindet . Also wenn mehrer User etwas lesen und schreiben , gewinnt erstmal das lesen und dann wird geschrieben , ergo ist der select wert bei nicht gesperrter Tabelle schon lange veraltet beim weiterverarbeiten .

Kommentar von wotan38 ,

Bei professionellem Arbeiten mit Datenbanken werden Zugriffe transaktionsgesteuert abgewickelt. Man kann damit auch die Reihenfolge der Verarbeitung beeinflussen. Wenn ich Methoden anwende, wo das nicht geht, ist meine Methode falsch. Auch wenn 99 von 100 Zugriffen richtig abgewickelt werden oder nur dann, wenn ich alleine in der Datenbank arbeite. Das ist Wischi-Waschi-Logik.

Ich kann der Datenbank nicht sagen, den Satz, den ich geschrieben habe, möchte ich haben. Die Datenbank kennt mich nicht und kann das gar nicht korrekt bearbeiten.

Kommentar von RakonDark ,

Und ein Fehler hat sich eingeschlichen , wenn mehrere Datensätze mit nur genau einem Insert gemacht werden , dann ist last_insert_id der erste Datensatz und leider nicht der letzte Datensatz .

Kommentar von klugshicer ,

Vielen Dank für die Ausführung bei meinem kleinen Projekt wird das zwar keine Rolle spielen - aber in einer ERP wäre ein last-insert-id ohne gesperrte Datenbank natürlich Mist.

Das ist wahrscheinlich auch der Grund, warum MS Word z.B. Datenquellen für Serienbriefe grundsätzlich im exklusiven Modus öffnet.

Antwort
von wotan38, 10

Von wenigen berechtigten Ausnahmen abgesehen ist ein AUTOINCREMENT für Leute, die die Datenbankkonzeption noch nicht ganz verstanden haben. Wenn ein numerischer Schlüssel nur der internen Verknüpfung dient, mich der Wert nicht interessiert und ich ihn auch nicht wissen muss, dann kann ich ihn verwenden. Wenn ich den Wert aber benötige, erzeuge ich den Wert selber und kenn diesen Wert auch.

Man kann doch nicht einerseits eine Methode wählen, wo ich den Wert nicht erfahre und anderseits den Wert haben wollen (nur um eine Addition zu sparen).

Es gibt eine Menge Probleme, die man vermeiden kann, in dem man die automatische Nummerierung nicht benutzt. Man muss das einfach wissen, wo man sowas machen kann oder es lieber bleiben lässt.

Es gibt im Zusammenhang mit maschinell unterstützten Verfahren der Konzipierung Philosophien, die für jede Tabelle einen solchen Primärschlüssel vorsehen. Dafür ist die Anweisung AUTOINCREMENT gedacht.   

Kommentar von RakonDark ,

Du hast es auch nicht verstanden. Bei Multiusersystemen kannst Du mit Addition gar nichts anfangen. Weil Du gar nicht Weisst ob nicht schon neue Datensätze vorhanden sind. Und ganz wichtig , man bekommt ja den Autor , nur halt nicht den letzten wert in der Tabelle. Du hast da philosophischen unsinn geschrieben wenn es um My SQL und mehr Benutzer Systeme geht. Wenn Du bzw nur dein Programm handelt dann ginge das aber sobald mehrere Prozesse laufen hast Du ein Problem die Eindeutigkeit zu bestimmen und z.b. Genau diesen Datensatz wieder zu bearbeiten. Da es genug Datensätze gibt wo z.b. Name und Datum und Geburtsdatum mehrfach vorkommen. Bei einer Krankenkasse endete es damit das der Eingeben dann noch ein Schritt machen muss und die x fachen Datensätze manuell geprüfte und der jeweilige Datensatz ausgewählt werden muss. Dabei darf dann der Eingeben aus Datenschutz auch nicht alles vom Datensatz sehen. Das war so der alte DOS Stil also da wo man eigentlich noch nicht wirklich mehrfachbenutzer Systeme als Standart hat und es auch keine Stateless Prozesse bzw Asynchrone Prozesse gab. Sprich vor 30 Jahren.

Kommentar von wotan38 ,

Ich habe bei einem Kunden eine Anwendung mit 4 Arbeitsplätzen laufen, wo z.B. fortlaufende Rechnungsnummern benötigt werden. Die aktuell letzte Nr. ist gesondert bei den Einstellungen gespeichert. Beim Anfordern der nächsten freien Nr. wird per

UPDATE Einstellungen SET maxrechnr = maxrechnr + 1 

die zuletzt vergebene um 1 erhöht und der Satz gesperrt. Anschließend wird per SELECT die neue Nr gelesen. Dann folgt ein COMMIT zum Abschluss, der den gesperrten Satz wieder freigibt und die aktuelle Nr für andere Anwender wieder verfügbar macht. So können auf allen 4 Arbeitsplätzen gleichzeitig ohne sich gegenseitig ins Gehege zu kommen Rechnungen geschrieben werden. Ich benutze allerdings nicht MYSQL, sondern eine professionelle Datenbank DB2 von IBM. Wenn ich so sehe, was die Leute hier für Probleme mit MYSQL und Änlichem haben, weiß ich nicht: Können die das nicht richtig oder geht sowas mit diesen Datenbanken gar nicht.

Übrigens: Multiusing habe ich schon in den 80-ger Jahren gemacht, und das noch ohne Datenbanken. DOS gab es damals auch noch nicht.

Kommentar von RakonDark ,

in einer seqienziellen Produktion mag das funktionieren aber nicht in einer parallelen und genau dafür wurde der Auto wert erdacht. Deine Aussage ist heut zu tage nur ein ganz spezieller Fall und schon lange ungültig.

Kommentar von wotan38 ,

Aber die Probleme, die die Leute damit haben, sind noch gültig. Schau Dich doch mal hier um, mit welchen banalen Dingen viele Schwierigkeiten haben.

Antwort
von Xandoo94, 8

lastInsertid heißt das Stichwort

Antwort
von coding24, 18

Benutze dafür LAST_INSERT_ID:

http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_last-...

Aber vorsicht vor Race-Conditions!

Kommentar von klugshicer ,

Interessante Funktion - vielen Dank

Antwort
von LeonardM, 26

Du musst bei insert keine id eingeben wenns eh auto increment hat..

Wenn du trotzdem die letzte id haben willsz in deiner Tabelle würde ich folgendes machen

SELECT id FROM tabelle ORDER BY id DESC LIMIT 1

Kommentar von LeonardM ,

und ja is mir klar das das nicht die allerbeste lösung ist

Antwort
von daCypher, 31

Ich würde einfach die höchste ID abfragen.

SELECT MAX(meineIDSpalte) FROM meineTabelle;

Damit geht es auch auf anderen Datenbankservern. Die vorgeschlagene Funktion von Coding24 geht z.B. nur bei MySQL.

Kommentar von klugshicer ,

Meine Frage bezog sich ja auch auf MySQL

Kommentar von coding24 ,

Dein Ansatz ruft auch ein vollkommen falsches Verhalten hervor.

Die LastInsertId ist nicht gleich der höchsten ID. Wenn ich die letzten 3 Datensätze lösche, ist dein Ergebnis "LastInsertId-3" - und damit falsch.

Für MS SQL gibt es (ebenso wie für PGSQL) Funktionen, die die letzte eingefügte ID sauber zurückgeben. Warum will man dann etwas bauen, das grob fahrlässig falsche Informationen zurückliefert?

Kommentar von daCypher ,

"Grob fahrlässig falsche Informationen" finde ich etwas übertrieben. Die Frage war ja, wie man die ID von einem einzelnen, grade eingefügten Datensatz zurückkriegt. Ich glaube nicht, dass der Fragesteller es so meinte, dass er einen Datensatz einfügt, dann beliebig viele Datensätze von hinten löscht und dann erst die ID haben will.

Außerdem wollte ich nur einen Ansatz geben, wie man das gleiche Problem auf verschiedenen Servern lösen kann, ohne wissen zu müssen, dass es bei MySQL "LAST_INSERT_ID()", bei MS SQL "@@IDENTITY" und z.B. bei Oracle keine eigene Funktion oder Variable gibt.

Kommentar von RakonDark ,

Sorry, aber die Aussage meint , ich bin an einem einzelplatzsystem ala access und hab nur einen datensatz . wenn wir aber bei webservern asynconer art sind , weiss man eh nicht wann was wie wo eingetragen wird , deswegen gibt es ja die atom funktion last_insert_id .

Kommentar von Fregrin ,

"weiss man eh nicht wann was wie wo eingetragen wird"
öhm, Stichwort "Transaktionen"

Kommentar von coding24 ,

Du hast den Punkt erkannt:

Die Frage war ja, wie man die ID von einem einzelnen, grade eingefügten Datensatz zurückkriegt.

Und genau das ist das Problem an deiner Lösung - diese ID bekommst du eben dann nicht zwangsweise zurück. Du kannst Glück haben, dass zwischendurch nicht mal eben ein weiterer Datensatz eingefügt (oder gelöscht) wurde. Dann funktioniert deine Lösung. Sobald du aber eine Seite hast, die durch Zufall zwei User hat, die parallel Datensätze einpflegen, ist dein Ansatz nicht zuverlässig. Dann bekomme ich nur irgendeine ID - und nicht die zuletzt eingefügte.

Keine passende Antwort gefunden?

Fragen Sie die Community