Doktor Knallcharge: MySQL-Fehler 1062, Doppler-ID finden

Beitrag lesen

mysql> insert into tabelle (wert) values ("a") on duplicate key update id=last_insert_id(id);

Füge "a" ein in Tabelle, wenn Doppler dann verändere den Key(also ID), was aber ja kontraproduktiv wäre und somit nicht sein kann. Also was genau macht "on duplicate key update id=last_insert_id(id)"? Für Dummys ;-)

Das, was nach on duplicate key kommt, wird ausgeführt, sobald eben genau der beschriebene Fall Eintritt, ein Schlüsselwert würde doppelt vorhanden sein. Soweit ist dir das ja schon klar.Beachte, dass das Update die Zeile betrifft, in der der doppelte Wert vorhanden ist.

last_insert_id() liefert, auch das ist dir natürlich bekannt, die ID der letzten eingefügten Zeile.

last_insert_id(argument) hingegen _setzt_ den Wert, der beim nächsten Aufruf von last_insert_id() zurückgegeben wird, und gibt selbst ebenfalls schon den übergebenen Wert zurück.

Beispiel:

mysql> insert into tabelle irgendwelches_blabla;

mysql> select last_insert_id();  # liefert ID der eben eingefügten Zeile
+------------------+
| last_insert_id() |
+------------------+
|               42 |
+------------------+

mysql> select last_insert_id(23); # setzt den last-insert-id-Wert für diesen und alle folgenden Aufrufe auf 23
+--------------------+
| last_insert_id(23) |
+--------------------+
|                 23 |
+--------------------+

mysql> select last_insert_id(); # liefert, wie eben festgelegt, 23
+------------------+
| last_insert_id() |
+------------------+
|               23 |
+------------------+

Beachte den dritten Aufruf von last_insert_id(): Es wurde zwischen erstem und drittem Aufruf keine Zeile eingefügt, trotzdem liefert last_insert_id() nicht mehr 42 wie eingangs, sondern 23 – wie im zweiten Aufruf festgelegt.

Zu deiner Problemlösung:

mysql> insert into tabelle (wert) values ("a") on duplicate key update id=last_insert_id(id);

Angenommen, "a" ist bereits vorhanden, deshalb wird jetzt on duplicate key update … ausgeführt.

1. Offensichtlich wird hier erstmal last_insert_id mit der id der betreffenden, schon vorhandenen Zeile aufgerufen ("last_insert_id(id)").

2. a) last_insert_id merkt sich die Spalte id der vorhandenen Zeile.
   b) last_insert_id gibt die Spalte id der vorhandenen Zeile zurück.

3. Die Spalte id der vorhandenen Zeile wird mit ihrem eigenen Wert überschrieben, denn last_insert_id() gibt ja, siehe 2b), genau diesen zurück (de facto passiert gar nichts, denn MySQL ändert nichts, was nicht geändert werden muss).

Zu guter Letzt bekommst du wegen 2a) mit allen nachfolgenden Aufrufen von last_insert_id immer wieder die ID der betreffenden Zeile geliefert (lies: so lange, bis eine neue Zeile eingefügt und damit eine neue ID erzeugt wird oder du last_insert_id wieder mit Argument aufrufst).

Da, wie in 3. schon beschrieben, jedoch keine Änderung vorgenommen wird, ist der Rückgabewert von row_count() 0. Anhand dieses Wertes lässt sich unterscheiden, ob eine neue Zeile eingefügt wurde (row_count() == 1, neue ID in last_insert_id()) oder bereits eine vorhanden war (row_count() < 1, alte ID in last_insert_id()).