id des betroffenen Datensatzes
calconeon
- php
Hi,
wenn ich über INSERT INTO in eine MySQL-DB einen Eintrag gemacht habe, wie erhalte ich dann die ID des betroffenen Datensatzes, wenn ein Auto-Inkrement-Primär-Schlüsel-Feld in der Tabelle ist?
Gibt es dafür eine Funktion oder muss ich dafür den letzen Eintrag oder so SELECT und von dort die ID nehmen?
Dankeschön
MfG Ronny
Hallo Ronny!
Gibt es dafür eine Funktion [...]
Ja. Siehe mysql_insert_id().
MfG
Götz
Hi Ronny,
wenn ich über INSERT INTO in eine MySQL-DB einen Eintrag gemacht habe, wie erhalte ich dann die ID des betroffenen Datensatzes, wenn ein Auto-Inkrement-Primär-Schlüsel-Feld in der Tabelle ist?
Für was benötigst du denn direkt nach dem INSERT die ID?
Vielleicht kannst du dies auch mit einem anderem Wert lösen, welchen du bereits hast...
...muss ich dafür den letzen Eintrag oder so SELECT und von dort die ID nehmen?
Yepp... würde ich jetzt so sehen, sofern o.g. nicht möglich ist...
Viele Grüße,
Erri
Hello Erri,
Für was benötigst du denn direkt nach dem INSERT die ID?
Das ist jetzt eine interessante Frage. Bitte erklär mir doch mal, wieso Du sie gestellt hast.
Vielleicht kannst du dies auch mit einem anderem Wert lösen, welchen du bereits hast...
Vielleicht mit 'Bratkartoffel'? Wenn man sich das rechtzeitig als Konstante deklariert, hätte man es immer zur Verfügung ;-)
...muss ich dafür den letzen Eintrag oder so SELECT und von dort die ID nehmen?
Yepp... würde ich jetzt so sehen, sofern o.g. nicht möglich ist...
Jedes funktionierende SQL-System liefert bei einem Insert auf einen Autoincrement-Key mindestens letzten erzeugten Wert zurück. Bei MySQL muss diese Abfrage aber sofort als nächstes Statement auf das Insert-Statement erfolgen. PHP stellt hierfür die Funktion mysql_insert_id() http://de.php.net/manual/de/function.mysql-insert-id.php zur Verfügung, die aber nicht mit dem vollenn Schlüsselvorrat von MySQL umgehen kann. Wenn man den nutzen möchte, sollte man sich eine eigene kleine Funktion mit dem passenden SQL-Statement schreiben.
Außerdem kann mittels SQL = "show table status" auch die nächste fällige Insert-ID einer Tabelle besorgen. Die ist dann aber tabellenbezogen, und nicht verbindungsbezogen, sagt also nichts über die gerade erstellte Relation einer Verbindung aus, sondern nur über die nächste, sofern man die Tabelle VOR dem "show table status" gesperrt hat und nicht vor dem erfolgten Insert wieder entsperrt.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hallo Tom,
Jedes funktionierende SQL-System liefert bei einem Insert auf einen Autoincrement-Key mindestens letzten erzeugten Wert zurück. Bei MySQL muss diese Abfrage aber sofort als nächstes Statement auf das Insert-Statement erfolgen. PHP stellt hierfür die Funktion mysql_insert_id() http://de.php.net/manual/de/function.mysql-insert-id.php zur Verfügung, die aber nicht mit dem vollenn Schlüsselvorrat von MySQL umgehen kann. Wenn man den nutzen möchte, sollte man sich eine eigene kleine Funktion mit dem passenden SQL-Statement schreiben.
Kann man eigentlich bei Mysql-Queries, die in einem Script-Code direkt hintereinander stehen, davon ausgehen, dass sie von der DB auch direkt hintereinander ausgeführt werden und nicht eventuell doch ein parallel ausgeführtes Script eine andere Query 'dazwischenschiebt'?
Ich befürchte, wenn man wirklich sicher gehen will, _muss_ man die entsprechende Tabelle in jedem Fall LOCKEN...
Gruß,
Hx
Hello,
Kann man eigentlich bei Mysql-Queries, die in einem Script-Code direkt hintereinander stehen, davon ausgehen, dass sie von der DB auch direkt hintereinander ausgeführt werden und nicht eventuell doch ein parallel ausgeführtes Script eine andere Query 'dazwischenschiebt'?
Man kann davon ausgehen, dass beide Queries als einzelne Statements behandelt werden. PHP wird ja das zweite erst abschicken, wenn das Ergebnis des ersten eingetroffen ist. Di DB kann aber eine Menge einzelne Statements geschuppt annehmen. Also angenommen werden sie der reihe nach, aber das erst muss dazu noch nicht fertig ausgeführt werden, bevor das zweite angenommen wird.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
»» Hi,
... PHP wird ja das zweite erst abschicken, wenn das Ergebnis des ersten eingetroffen ist. Di DB kann aber eine Menge einzelne Statements geschuppt annehmen aber das erst muss dazu noch nicht fertig ausgeführt werden, bevor das zweite angenommen wird.
Vielleicht mach ich ja einen Denkfehler - aber wärs denn gerade deshalb nicht möglich, dass zwischen dem Abschicken des ersten und zweiten Statements aus dem _einen_ Script, Statements aus einem oder mehreren parallel verarbeiteten Scripten _anderen_ Scripten 'dazwischengeschuppt' werden?
Definitiv ausschließen läßt sich das nicht, denke ich
(Wie gesagt ev. mir einem Fehler in demselben - dem Denken mein ich.)
Herzlich,
hx
Hallo,
Vielleicht mach ich ja einen Denkfehler - aber wärs denn gerade deshalb nicht möglich, dass zwischen dem Abschicken des ersten und zweiten Statements aus dem _einen_ Script, Statements aus einem oder mehreren parallel verarbeiteten Scripten _anderen_ Scripten 'dazwischengeschuppt' werden?
Um sicher zu gehen, musst Du die Funktion mit dem Parameter nutzen.
int mysql_insert_id ( [resource link_identifier] )
http://de.php.net/manual/en/function.mysql-insert-id.php
Lies den Kommentar von Baak (01-Oct-2004 08:04).
Durch die Angabe des link_identifier ist sichergestellt, dass nur für _diese_ Verbindung generierte IDs zurückgegeben werden.
viele Grüße
Axel
Hello,
Um sicher zu gehen, musst Du die Funktion mit dem Parameter nutzen.
int mysql_insert_id ( [resource link_identifier] )
Sorry, da habe ich vielleicht für Verwirrung gesorgt.
Für jede Connection werden bestimmte Parameter und Variablen von einer SQL-Schnittstelle immer bereit gehalten. Die Letzte Insert ID gehört genauso dazu, wie das letzte Statement. Ob MySQL das auch irgendwie reproduzieren kann, weiß ich allerdings nicht.
Resultsets werden für eine Connection bei MySQL i.d.R. 9 Stück rückwärtig gehalten. Wenn man vergisst, die wieder freizugeben, bekommt man den Fehler, dass Resultset 10 nicht mehr definiert ist. Das kann bei mangelndem Pufferspeicher ausnahmsweise auch schon früher geschehen.
Die MySQL-API ind PHP stellt also nur eine sehr eingeschränkte Abstraktionsschicht dar. Die Grenzen liegen sehr eng an den tatsächlichen Beschränkungen des DBMS. Wenn man mal 10GB Hauptspeicher als Normal ansehen kann, ist das vielleicht auch vorbei, wenn bis dahin die M$-Freunde nicht neue Anwendungen ersonnen haben, die alle Ressourcen fressen.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hallo Axel, hallo Tom,
(Falls Ihr das noch lest - Sorry ich bin erst jetzt wieder im Forum...)
@TOM:
Danke für die Kellen aus Deinem enzyklopädischen Wissen - hat mein prinzipielles Verständnis erweitert.
@Axel:
Vielen Dank für den ganz konkreten Hinweis. Jetzt hab ichs kapiert - die last_insert_id gehört also zu den per-Connection erstellten und bereitgehaltenen Variablen; d.h. ich kann meine obigen Gedanken streichen, sofern ich die entsprechende resource-id immer mitübergebe.
Wieder einen 'breadcrumb' verinnerlicht.
Danke nochmals.
hx
Hallo,
d.h. ich kann meine obigen Gedanken streichen, sofern ich die entsprechende resource-id immer mitübergebe.
Wieder einen 'breadcrumb' verinnerlicht.
Es muss noch darauf hingewiesen werden - und das könnte ein etwas größeres Stück (hartes) 'Brot' sein ;-) - dass bei der Herstellung der Verbindung in diesem Fall zu gewährleisten ist, dass es sich auch um eine _exklusive_ verbindung handelt. Hierzu reicht der Standard-Aufruf
mysql_connect($server, $user, $pass);
nicht aus, denn: (Zitat aus http://www.php.net/manual/de/function.mysql-connect.php)
"Für den Fall, dass ein zweiter Aufruf von mysql_connect() mit den gleichen Argumenten erfolgt, wird keine neue Verbindung aufgebaut, sondern die Verbindungs-Kennung der schon bestehenden Verbindung zurückgeliefert."
[was ja im Falle von zwei zeitgleich verarbeiteten Scripten bzw. zwei nahe beieinanderliegenden HTTP-Aufrufen des gleichen Scripts durchaus der Fall sein kann...]
Wenn man also absolut sicher gehen will, muss die Verbindung über:
mysql_connect($server, $user, $pass, TRUE) [Der vierte Parameter bewirkt dén Aufbau einer _neuen_ Verbindung.]
aufgebaut werden und darüberhinaus sichergestellt sein, dass diese neue Verbindung ihrerseits auch nicht von anderen Scriptaufrufen mit gleichen Insert-Statements verwendet werden kann, d.h. also dass dort dann jeweils auch eine _neue_ Verbindung verwendet wird.
Hier muss man dann allerdings aufpassen, dass diese Verbindungen nach Gebrauch auch wieder geschlossen werden. Denn je nach PHP- und MySQL-Konfiguration (persistente Verbindungen) könnte man da andernfalls einen DB-Blocker gebären.
(AFAIK wird eine bestehende DB-Verbindung nach Beendigung des Scripts z.B. nicht automatisch geschlossen, wenn PHP als Apache-Modul läuft.)
Grüße,
Sancho
Hello,
"Für den Fall, dass ein zweiter Aufruf von mysql_connect() mit den gleichen Argumenten erfolgt, wird keine neue Verbindung aufgebaut, sondern die Verbindungs-Kennung der schon bestehenden Verbindung zurückgeliefert."
[was ja im Falle von zwei zeitgleich verarbeiteten Scripten bzw. zwei nahe beieinanderliegenden HTTP-Aufrufen des gleichen Scripts durchaus der Fall sein kann...]
Ein PHP-Script betreibt kein automatisches Threading in dem Resource- und Connection-Handles vererbt werden könnten. Die Befehle in einem Script werden also immer sequentiell abgearbeitet. Interrupting gibt es auch nicht. Es besteht also keine Gefahr, dass zwei direkt aufeinanderfolgende Befehle nicht auch dirket nacheinander abgearbeitet werden.
Das hat allerdings nichts mit der Datenbasis zu tun. Zwei direkt aufeinander folgende Zugriffe auf die Datenbasis sind nicht atomar.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hallo HendrikX, hallo Tom,
@Tom:
"Für den Fall, dass ein zweiter Aufruf von mysql_connect() mit den gleichen Argumenten erfolgt, wird keine neue Verbindung aufgebaut, sondern die Verbindungs-Kennung der schon bestehenden Verbindung zurückgeliefert."
»»
[was ja im Falle von zwei zeitgleich verarbeiteten Scripten bzw. zwei nahe beieinanderliegenden HTTP-Aufrufen des »» »» gleichen Scripts durchaus der Fall sein kann...]Ein PHP-Script betreibt kein automatisches Threading in dem Resource- und Connection-Handles vererbt werden könnten.
(...)
Hastu völlig recht.
Das Zitat bezieht sich natürlich nur auf mehrere Aufrufe von mysql_connect innerhalb _eines_ verarbeiteten Scripts. Wenn dasselbe Script von _mehreren_ PHP-Interpreter-Instanzen _zeitgleich_ verarbeitet wird - z.B. weil es von verschiedenen Clients unmittelbar nacheinander per HTTP abgerufen wird - dann wird natürlich pro Interpreter-Instanz jeweils eine neue Verbindung hergestellt. Habe das mal mit folgendem Script getestet (W2K/Apache 2.0.52/PHP 5.0.2):
<?php // test.php
$CNX = mysql_connect('localhost', '[user]', '[pass]');
mysql_select_db('[dbname]', $CNX);
echo "Verbindungs-Kennung: $CNX <br />";
mysql_query("INSERT INTO [tabelle mit auto-inkrement-Spalte] SET [feld] = '[wert]', $CNX");
if (isset($_GET['wait']))
{
echo 'Verarbeitung dauert länger...<br />';
sleep(15);
}
echo 'LAST_INSERT_ID: ', mysql_insert_id($CNX);
?>
Beim Aufruf über 'test.php?wait=1' gibt mysql_insert_id($CNX) immer die jeweils richtige ID der letzten Einfügung zurück, auch wenn ich während der Sleep-Pause in einem anderen Browser-Tab mehrfach 'test.php' [ohne $_GET-Parameter] aufrufe.
...
Aufruf 'test.php' [ohne $_GET-Parameter, in einem anderen Browser-Tab]
Ausgabe :
Verbindungs-Kennung: Resource id #1
LAST_INSERT_ID: 1
Wiederholter Aufruf 'test.php'
Ausgabe :
Verbindungs-Kennung: Resource id #1
LAST_INSERT_ID: 2
Wiederholter Aufruf 'test.php'
Ausgabe :
Verbindungs-Kennung: Resource id #1
LAST_INSERT_ID: 3
...
Verbindungs-Kennung: Resource id #1
Verarbeitung dauert länger...
LAST_INSERT_ID: 0
[PHPs 'Resource id' ist nur eine Script-interne Verbindungs-Kennung.]
Die Verbindung, die für 'test.php?wait=1' aufgebaut wurde, bleibt für die Verarbeitungszeit dieses Scripts ausschließlich diesem Script bzw. der entsprechenden verarbeitenden Interpreter-Instanz vorbehalten.
@HendrikX:
Also ist hier wohl doch kein 'hartes Brot' zu befürchten (sondern - zumindest für mich - nur dieser zusätzliche 'Kenntnis-Krümel' entstanden; Ihr beide habt das ja vielleicht eh scho gwusst. ;-)
Grüße,
Sancho
Hi Sancho,
Also ist hier wohl doch kein 'hartes Brot' zu befürchten (sondern - zumindest für mich - nur dieser zusätzliche 'Kenntnis-Krümel' entstanden; Ihr beide habt das ja vielleicht eh scho gwusst. ;-)
_So_genau_ hab ich das nicht 'gwusst', btw. darüber eigtl. noch gar nicht nachgedacht, wie das bei mehreren gleichzeitig laufenden Interpreter-Instanzen genau vor sich geht mit den respektiven MySQL-Verbindungen.
Übernehme also auch diesen Krümel dankend in mein Sammelsurium.
(Vielleicht wird ja irgendwann mal eine akzeptable Panade daraus... :)
Gruß,
hx
Hello,
@Tom:
"Für den Fall, dass ein zweiter Aufruf von mysql_connect() mit den gleichen Argumenten erfolgt, wird keine neue Verbindung aufgebaut, sondern die Verbindungs-Kennung der schon bestehenden Verbindung zurückgeliefert."
»»
[was ja im Falle von zwei zeitgleich verarbeiteten Scripten bzw. zwei nahe beieinanderliegenden HTTP-Aufrufen des »» »» gleichen Scripts durchaus der Fall sein kann...]Ein PHP-Script betreibt kein automatisches Threading in dem Resource- und Connection-Handles vererbt werden könnten.
(...)Hastu völlig recht.
Das Zitat bezieht sich natürlich nur auf mehrere Aufrufe von mysql_connect innerhalb _eines_ verarbeiteten Scripts.
Warum sollte ich zur selben Datenbank innerhalb eines Scriptes mehrere Verbindungen aunfbauen?
Und selbst wenn ich es tue, merke ich mir doch, unter welcher Connection-Nummer ich welchen DBServer angesprochen habe und gebe sie auch immer mit an.
Wer natürlich diese faule Programmierweise pflegt, sodass sich PHP seinen Teil denken muss, braucht sich auch nicht über falsche Ergebnisse zu wundern.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom,
Warum sollte ich zur selben Datenbank innerhalb eines Scriptes mehrere Verbindungen aunfbauen?
Und selbst wenn ich es tue, merke ich mir doch, unter welcher Connection-Nummer ich welchen DBServer angesprochen habe und gebe sie auch immer mit an.Wer natürlich diese faule Programmierweise pflegt, sodass sich PHP seinen Teil denken muss, braucht sich auch nicht über falsche Ergebnisse zu wundern.
Ich glaube nicht, dass es Sancho darum ging.
So wie ich ihn verstanden habe, war ihm nicht klar, dass - wenn einunddasselbe Script (mit Datenbankanbindung) zeitgleich von _verschiedenen_ Interpreter-Instanzen abgearbeitet wird, jede dieser Instanzen grundsätzlich eine eigene MySQL-Verbindung verwendet. Da es ihm nicht klar war, hat er's ausprobiert und uns daraufhin das Ergebnis mitgeteilt.
Dass das für andere möglicherweise keine neue Erkenntnis ist, hat er auch noch angemerkt. Gegen all das ist wenig einzuwenden.
Mir hats ein bisschen weitergeholfen im Hinblick auf diese spezielle per-Connection-Fragestellung.
Gruß,
hx
»» wenn ich über INSERT INTO in eine MySQL-DB einen Eintrag gemacht habe, wie erhalte ich dann die ID des betroffenen Datensatzes, wenn ein Auto-Inkrement-Primär-Schlüsel-Feld in der Tabelle ist?
Hallo,
schau mal unter http://de3.php.net/manual/de/function.mysql-insert-id.php !
;)
Ciao,
Andreas