Normalerweise kann ich eine Zeile in eine MySQL-Tabelle einfügen und die last_insert_id
Rückseite erhalten. Jetzt möchte ich jedoch viele Zeilen in die Tabelle einfügen und ein Array von IDs zurückerhalten. Weiß jemand, wie ich das machen kann?
Es gibt einige ähnliche Fragen, aber sie sind nicht genau gleich. Ich möchte die neue ID nicht in eine temporäre Tabelle einfügen. Ich möchte nur das Array von IDs zurückbekommen.
Kann ich die lastInsertId aus einer Masseneinfügung abrufen?
MySQL-Anweisung zum Einfügen und Auswählen mehrerer Zeilen mit last_insert_id ()
mysql
bulkinsert
Friedensstiftung
quelle
quelle
OUTPUT
Klausel simulieren . Ich glaube, Sie können dies mit einem Trigger in MySQL tunAntworten:
Alter Thread, der sich aber nur damit befasst hat. Wenn Sie InnoDB in einer neueren Version von MySQL verwenden, können Sie die Liste der IDs mit
LAST_INSERT_ID()
und abrufenROW_COUNT()
.InnoDB garantiert fortlaufende Nummern für AUTO INCREMENT bei Masseneinfügungen, sofern diese
innodb_autoinc_lock_mode
auf 0 (traditionell) oder 1 (aufeinanderfolgend) gesetzt sind. Folglich können Sie die erste ID vonLAST_INSERT_ID()
und die letzte durch Hinzufügen erhaltenROW_COUNT()-1
.quelle
Ich kann mir nur vorstellen, dass dies möglich ist, wenn Sie für jeden Satz eingefügter Zeilen (guid) eine eindeutige Kennung speichern und dann die Zeilen-IDs auswählen. z.B:
INSERT INTO t1 (SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table); COMMIT; SELECT id FROM t1 WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70';
Sie können die Guid auch in der Datenbank mithilfe von generieren
uuid()
quelle
Nehmen wir an, wir haben eine Tabelle namens Versuchbar mit zwei Spalten uid, col1, wobei uid ein automatisches Inkrementfeld ist. Wenn Sie wie folgt vorgehen, werden alle in die Ergebnismenge eingefügten IDs zurückgegeben. Sie können die Ergebnismenge durchlaufen und Ihre IDs abrufen. Mir ist klar, dass dies ein alter Beitrag ist und diese Lösung möglicherweise nicht in jedem Fall funktioniert. Aber für andere könnte es sein und deshalb antworte ich darauf.
# lock the table lock tables temptable write; #bulk insert the rows; insert into temptable(col1) values(1),(2),(3),(4); #get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op. set @first_id = last_insert_id(); #now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's select uid from temptable where uid >=@first_id; #now that you are done don't forget to unlock the table. unlock tables;
quelle
Ich denke, Sie müssen entweder die Transaktions-ID in Ihrer Anwendung oder die Artikel-ID in Ihrer Anwendung verarbeiten, um dies fehlerfrei zu tun.
Ein Weg, dies zu tun, der funktionieren könnte, vorausgesetzt, alle Ihre Einfügungen sind erfolgreich (!), Ist der folgende:
Sie können dann die eingefügten IDs mit einer Schleife für die Anzahl der betroffenen Zeilen abrufen, beginnend mit lastid (dies ist die erste eingefügte ID der Masseneinfügung). Und so habe ich überprüft, ob es perfekt funktioniert. Sei nur vorsichtig, dass HeidiSQL zum Beispiel nicht den richtigen Wert für ROW_COUNT () zurückgibt, wahrscheinlich weil es eine beschissene GUI ist, die zufällige Scheiße macht Kommandozeile oder PHP mysqli -
START TRANSACTION; BEGIN; INSERT into test (b) VALUES ('1'),('2'),('3'); SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount; COMMIT;
In PHP sieht es so aus (local_sqle ist ein direkter Aufruf von mysqli_query, local_sqlec ist ein Aufruf von mysqli_query + Konvertieren der Ergebnismenge in ein PHP-Array):
local_sqle("START TRANSACTION; BEGIN; INSERT into test (b) VALUES ('1'),('2'),('3');"); $r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;"); local_sqle(" COMMIT;"); $i=0; echo "last id =".($r[0]['lastid'])."<br>"; echo "Row count =".($r[0]['rowcount'])."<br>"; while($i<$r[0]['rowcount']){ echo "inserted id =".($r[0]['lastid']+$i)."<br>"; $i++; }
Der Grund, warum die Abfragen getrennt sind, liegt darin, dass ich mein Ergebnis sonst nicht mit meinen eigenen Funktionen erhalten würde. Wenn Sie dies mit Standardfunktionen tun, können Sie es wieder in eine Anweisung setzen und dann das gewünschte Ergebnis abrufen (es sollte die Ergebnisnummer sein 2 - vorausgesetzt, Sie verwenden eine Erweiterung, die mehr als eine Ergebnismenge / Abfrage verarbeitet).
quelle
Ich wäre mir nicht sicher, ob der Wert für das automatische Inkrementieren das Element um 1 erhöht. Es wird große Probleme geben, wenn Ihre Datenbank über eine Master // Master-Replikation verfügt und der doppelte Ausschluss von auto_increment behoben wird. KI wird +2 statt +1 sein, auch wenn es noch einen Meister gibt, wird es zu +3 kommen. Wenn Sie also etwas weitergeben, wie AUTO_INCREMENT für 1 steigt, wird Ihr Projekt beendet.
Ich sehe nur einige gute Möglichkeiten, dies zu tun.
Dieses SQL-Snippet hat keine Probleme mit mehreren Mastern und liefert gute Ergebnisse, bis Sie nur noch eingefügte Datensätze benötigen. Bei mehreren Anforderungen ohne Transaktionen können andere Einfügungsdatensätze abgefangen werden.
START TRANSACTION; SELECT max(id) into @maxLastId FROM `main_table`; INSERT INTO `main_table` (`value`) VALUES ('first'), ('second') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`); SELECT `id` FROM `main_table` WHERE id > @maxLastId OR @maxLastId IS NULL; COMMIT;
(Wenn Sie auch aktualisierte Datensätze von DUPLICATE KEY UPDATE benötigen), müssen Sie die Datenbank ein wenig umgestalten, und SQL sieht wie folgt aus (sicher für Transaktionen und keine Transaktionen innerhalb einer Verbindung).
#START TRANSACTION INSERT INTO bulk_inserts VALUES (null); SET @blukTransactionId = LAST_INSERT_ID(); SELECT @blukTransactionId, LAST_INSERT_ID(); INSERT INTO `main_table` (`value`, `transaction_id`) VALUES ('first', @blukTransactionId), ('second', @blukTransactionId) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `transaction_id` = VALUES(`transaction_id`); SELECT @blukTransactionId, LAST_INSERT_ID(); SELECT id FROM `main_table` WHERE `transaction_id` = @blukTransactionId; #COMMIT
Beide Fälle sind transnational sicher. Erstens werden nur eingefügte Datensätze angezeigt und zweitens werden alle Datensätze sogar aktualisiert.
Auch diese Optionen funktionieren auch mit INSERT IGNORE ...
quelle
Dieser Thread ist alt, aber all diese Lösungen haben mir nicht geholfen, also habe ich mir meine eigenen ausgedacht.
Zählen Sie zunächst, wie viele Zeilen Sie einfügen möchten
Nehmen wir an, wir müssen 5 Zeilen hinzufügen:
LOCK TABLE tbl WRITE; SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'my_db' AND TABLE_NAME = 'tbl'
Verwenden Sie dann das soeben ausgewählte auto_increment, um die nächste Abfrage durchzuführen:
ALTER TABLE tbl AUTO_INCREMENT = {AUTO_INCREMENT}+5; UNLOCK TABLES;
Zum Schluss machen Sie Ihre Einsätze
Verwenden Sie den reservierten Autoincrement-Bereich, um eine ID einzufügen.
Warnung: Diese Lösung erfordert eine erhöhte Zugriffsebene auf die Tabellen. Aber normalerweise werden Bulk-Einfügungen von Crones und Importer-Skripten ausgeführt, und was nicht, kann ohnehin einen speziellen Zugriff erfordern. Sie würden dies nicht nur für ein paar Beilagen verwenden.
Dies kann dazu führen, dass nicht verwendete IDs nicht verwendet werden, wenn Sie ON DUPLICATE KEY UPDATE verwenden.
quelle
$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)"; $idArray = array(); foreach($array as $key) { mysql_query($query); array_push($idArray, mysql_insert_id()); } print_r($idArray);
quelle