¿Cómo puedo insertar muchas filas en una tabla MySQL y devolver las nuevas ID?

Normalmente puedo insertar una fila en una tabla MySQL y recuperar el last_insert_id . Ahora, sin embargo, quiero insertar a granel muchas filas en la tabla y obtener una serie de ID. ¿Alguien sabe cómo puedo hacer esto?

Hay algunas preguntas similares, pero no son exactamente lo mismo. No quiero insertar la nueva ID en ninguna tabla temporal; Solo quiero recuperar el conjunto de ID.

¿Puedo recuperar el lastInsertId de una inserción masiva?

Instrucción de inserción-selección de filas múltiples de Mysql con last_insert_id ()

El hilo antiguo, pero solo analicé esto, así que aquí va: si estás usando InnoDB en una versión reciente de MySQL, puedes obtener la lista de ID usando LAST_INSERT_ID () y ROW_COUNT ().

InnoDB garantiza números secuenciales para INCREMENTO AUTOMÁTICO al realizar inserciones masivas, siempre que innodb_autoinc_lock_mode esté configurado en 0 (tradicional) o 1 (consecutivo). En consecuencia, puede obtener el primer ID de LAST_INSERT_ID () y el último agregando ROW_COUNT () – 1.

La única forma en que puedo pensar que podría hacerse es almacenar un identificador único para cada conjunto de filas insertadas (guid) y luego seleccionar las identificaciones de fila. p.ej:

 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'; 

También puede generar el guid en la base de datos usando uuid()

Supongamos que tenemos una tabla llamada temptable con dos cols uid, col1 donde uid es un campo de incremento automático. Hacer algo como a continuación devolverá todas las identificaciones insertadas en el conjunto de resultados. Puede recorrer el conjunto de resultados y obtener su identificación. Me doy cuenta de que esta es una publicación anterior y esta solución podría no funcionar en todos los casos. Pero para otros podría y por eso estoy respondiendo.

 # 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; 

Creo que tendrá que manejar la identificación de la transacción en su aplicación, o la identificación del artículo en su aplicación para poder hacer esto sin problemas.

Una forma de hacer esto que podría funcionar, suponiendo que todas tus inserciones tengan éxito (!), Es la siguiente:

A continuación, puede obtener las identificaciones insertadas con un ciclo para el número de filas afectadas, comenzando con lastid (que es la primera identificación insertada de la inserción masiva). Y así, comprobé que funciona a la perfección … solo tenga cuidado de que HeidiSQL, por ejemplo, no devuelva el valor correcto para ROW_COUNT (), probablemente porque es una interfaz gráfica de usuario deshonesta que hace mierda al azar, no la pedimos, pero es perfectamente correcta desde cualquiera línea de comandos o PHP mysqli –

 START TRANSACTION; BEGIN; INSERT into test (b) VALUES ('1'),('2'),('3'); SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount; COMMIT; 

En PHP se ve así (local_sqle es una llamada directa a mysqli_query, local_sqlec es una llamada a mysqli_query + convert resultset a 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'])."
"; echo "Row count =".($r[0]['rowcount'])."
"; while($i< $r[0]['rowcount']){ echo "inserted id =".($r[0]['lastid']+$i)."
"; $i++; }

La razón por la que las consultas están separadas es porque de lo contrario no obtendría mi resultado utilizando mis propias funciones, si lo hace con funciones estándar, puede volver a colocarlo en una statement y luego recuperar el resultado que necesita (debe ser el número de resultado 2 – suponiendo que usa una extensión que maneja más de un conjunto de resultados / consulta).

 $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);