2010-11-24 5 views
14

EDIT: Dieser Fragetitel war ursprünglich: Woher kennt Doctrine die zuletzt eingefügte ID in MySQL? und war verwandt mit Doktrin ORM Mapper. Nach etwas graben fand ich heraus, dass diese Frage nicht mit Doctrine sondern mit PDO_MySQL, MySQL C API und schließlich - zu MySQL Client-Server-Kommunikation verbunden ist. Ich habe mich entschieden, den Titel zu ändern, vielleicht findet jemand eine Antwort auf seine/ihre Frage.Woher weiß PDO die zuletzt eingefügte ID in MySQL?

Für diejenigen, die nicht Lehre mit: Ich war neugierig, warum unten:

mysql_query("INSERT INTO category (name) VALUES('cat')"); 
echo mysql_insert_id(); 

oder ähnlich:

$pdo->exec("INSERT INTO category (name) VALUES('cat')"); 
echo $pdo->lastInsertId(); 

wird nur eine Position führen (ohne gesonderte SELECT LAST_INSERT_ID()) in Protokoll:

1701 Query INSERT INTO category (name) VALUES ('cat') 

Original Frage:

Ich habe 2 Tabellen:

category(id,name) 
product(id, name, categoryId) 

Ich habe neue Kategorie Objekt und Produkt-Objekt. Ich habe dem Produktobjekt ein Kategorieobjekt zugewiesen. Ich habe festgelegt keine ids:

$product = new Product(); 
$product->name = 'asdf'; 

$category = new Category(); 
$category->name = 'cat'; 

$product->Category = $category; 

Danach habe ich die Verbindung gespült und überprüfen MySQL Logs:

1684 Query START TRANSACTION 
1684 Query INSERT INTO category (name) VALUES ('cat') 
1684 Query INSERT INTO product (name, categoryid) VALUES ('asdf', '312') 
1684 Query COMMIT 

Wie haben Lehre wissen, dass die neu geschaffene Kategorie-ID 312 ist? Es gibt nichts anderes in den Protokollen.

Antwort

22

ich tat etwas Forschung und einige Quellcode sehen, so meine Antwort ein wenig falsch und nicht präzise sein könnte.

Zunächst einmal ist dies nicht wirklich auf Doctrine. Doktrin verwendet PDO_MYSQL. Aber intern PDO_MYSQL verwendet das gleiche wie mysql_insert_id Funktion - native MySQL C API Funktion - mysql_insert_id.

Der Grund, warum es keine separate SELECT LAST_INSERT_ID() liegt in der Tatsache ist, dass nach der Anweisung (in meinem Beispiel INSERT) ausgeführt wird, Server mit Daten und einige andere Dinge in OK Packet), enthalten reagiert insert_id inklusive. Also, wenn wir mysql_insert_id() feuern wir keine Verbindung zum Server, um insert_id zu erhalten - mysql-Bibliothek muss dies nicht tun - es hat bereits diesen Wert von der letzten Ausführung der Abfrage gespeichert (zumindest denke ich so nach der Analyse der Datei libmysql.c)

OK Packet ist hier beschrieben: MySQL Generic Response Packets - OK Packet

+0

Große Forschung. – jensgram

+0

Deshalb können wir es verwenden, ohne Angst vor Abfragerennen. Vielen Dank. – noober

1
+0

Aber das würde im Protokoll berücksichtigt werden, wäre es nicht? –

+0

@Pekka Eine ungebildete Vermutung: Könnte das Protokoll so konfiguriert werden, dass es * SELECT * nicht schreibt? – jensgram

+0

@jensgram könnte - oder es könnte konfiguriert werden, um die Ergebnisse von Funktionsaufrufen (nämlich 'LAST_INSERT_ID()') zu zeigen. Ich weiß nicht, wie die Abfrage-Protokolle funktionieren –

1

last_insert_id funktioniert nur für AUTO_INCREMENT Spalten. Es wird nicht funktionieren, wenn Sie manuell einen Wert in die Spalte AUTO_INCREMENT einfügen.

Die Doktrin wird funktionieren, weil es genau wie das Zuweisen einer NULL zu ihm ist (obwohl Sie nie das speziell schreiben). Dies löst das automatische Inkrement aus und liefert einen Wert für last_insert_id().

Ich habe hier ein jpg eingefügt, damit Sie es sehen können. Ich hoffe es hilft!

enter image description here

+0

Dies erklärt nicht, wie Lehre tatsächlich den Wert obwohl abruft. Es gibt keine Abfrage, die last_insert_id aufruft. – ryeguy

+0

Diese Antwort bezieht sich nicht auf die Frage. – prostynick