Estoy pasando un gran conjunto de datos en una tabla mysql a través de php utilizando comandos de inserción y me pregunto si es posible insertar aproximadamente 1000 filas a la vez a través de una consulta que no sea cada valor en el final de una cadena de una milla de largo y luego ejecutarlo. Estoy usando el marco codeigniter por lo que sus funciones también están disponibles para mí.insertar varias filas a través de una matriz php en mysql
Respuesta
Ensamblar una instrucción INSERT
con varias filas es mucho más rápido en MySQL que una instrucción INSERT
por fila.
Dicho esto, parece que podría encontrarse con problemas de manejo de cadenas en PHP, que es realmente un problema de algoritmo, no de lenguaje. Básicamente, cuando se trabaja con cadenas grandes, se debe minimizar la copia innecesaria. En primer lugar, esto significa que quiere evitar la concatenación. La forma más rápida y más eficiente desde el punto de vista de la memoria de construir una cadena grande, como insertar cientos de filas a la vez, es aprovechar la función implode()
y la asignación de matriz.
$sql = array();
foreach($data as $row) {
$sql[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $sql));
La ventaja de este enfoque es que no copia y volver a copiar la instrucción SQL que hasta ahora haya reunido con cada uno de concatenación; en cambio, PHP hace esto una vez en la declaración implode()
. Este es un gran triunfo.
Si tiene muchas columnas para armar, y una o más son muy largas, también podría construir un bucle interno para hacer lo mismo y usar implode()
para asignar la cláusula de valores a la matriz externa.
¡Gracias por eso! Por cierto, falta un corchete de cierre al final de la función si alguien está planeando copiarlo. mysql_real_query ('INSERT INTO table VALUES (texto, categoría)' .implode (','. $ sql)); – toofarsideways
¡Gracias! Fijo. (A menudo hago eso ...) – staticsan
También me acabo de dar cuenta, siendo tonto también la implosión (','. $ Sql)); debería ser implode (',', $ sql)); – toofarsideways
Puede preparar la consulta para insertar una fila usando la clase mysqli_stmt, y luego iterar sobre la matriz de datos. Algo así como:
$stmt = $db->stmt_init();
$stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, fld4) VALUES(?, ?, ?, ?)");
foreach($myarray as $row)
{
$stmt->bind_param('idsb', $row['fld1'], $row['fld2'], $row['fld3'], $row['fld4']);
$stmt->execute();
}
$stmt->close();
Donde '' idsb son los tipos de los datos que está vinculante (int, double, string, gota).
Recientemente ejecuté algunos benchmarks comparando la inserción masiva y las declaraciones de inserción preparadas como se menciona aquí. Para alrededor de 500 inserciones, el método de inserciones preparadas se completa entre 2.6-4.4 segundos y el método de inserción masiva en 0.12-0.35 segundos. Hubiera pensado que mysql habría "agrupado" estas declaraciones preparadas juntas y funcionara tan bien como las inserciones masivas, pero en una configuración predeterminada, la diferencia de rendimiento es enorme aparentemente. (Por cierto, todas las consultas de referencia se ejecutaban dentro de una sola transacción para cada prueba, para evitar el autocompromiso) – Motin
Bueno, usted no desea ejecutar 1.000 llamadas de consulta, pero haciendo esto está muy bien:
$stmt= array('array of statements');
$query= 'INSERT INTO yourtable (col1,col2,col3) VALUES ';
foreach($stmt AS $k => $v) {
$query.= '(' .$v. ')'; // NOTE: you'll have to change to suit
if ($k !== sizeof($stmt)-1) $query.= ', ';
}
$r= mysql_query($query);
Dependiendo de su fuente de datos, poblar la matriz podría ser tan fácil como abrir un archivo y el vertido contenidos en una matriz a través de file()
.
Usted podría utilizar siempre de LOAD DATA
mysql:
LOAD DATA LOCAL INFILE '/full/path/to/file/foo.csv' INTO TABLE `footable` FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'
a hacer las inserciones en lugar de utilizar un montón de INSERT
declaraciones.
Había investigado eso, pero necesito manipular los datos antes de insertarlos. Se me ha dado como un producto cartesiano de un conjunto de 1400 por 1400 valores int muchos de los cuales son cero. Necesito convertir eso en una relación de muchos a muchos utilizando una tabla intermedia para ahorrar espacio, por lo tanto, la necesidad de inserciones en oposición a una inserción masiva – toofarsideways
Siempre puede generar un archivo csv después de manipularlo y llamar a la instrucción mysql que carga los datos –
Creo que es útil saber que la ruta es local para su cliente SQL, y no en el servidor SQL. El archivo se carga en el servidor y luego lo lee. Pensé que el archivo ya debía estar en el servidor, que no es el caso. Si ya está en el servidor, elimine el bit 'LOCAL'. – Kyle
Sé que esto es una consulta de edad, pero yo estaba leyendo y que me gustaría añadir lo que he encontrado en otro lugar:
mysqli en PHP 5 es una ojbect con algunas buenas funciones que permitirán incrementar la velocidad el tiempo de inserción para la respuesta anterior:
$mysqli->autocommit(FALSE);
$mysqli->multi_query($sqlCombined);
$mysqli->autocommit(TRUE);
Desactivación de confirmación automática al insertar muchas filas en gran medida acelera la inserción, por lo desactivarlo, a continuación, ejecutar como se mencionó anteriormente, o simplemente hacer una cadena (sqlCombined) que es muchos inserto las declaraciones separadas por punto y coma y la consulta múltiple las manejarán bien.
Espero que esto ayude a alguien a ahorrar tiempo (buscando e insertando!)
R
Este es el error que obtuve al usar su idea: "Error fatal: Llamar a una función miembro autocommit() en null en /homepages/25/d402746174/htdocs/MoneyMachine/saveQuotes.php en la línea 30" – user3217883
múltiple inserto/lote inserto está ahora apoyado por CodeIgniter. Tuve el mismo problema Aunque es muy tarde para responder la pregunta, ayudará a alguien. Es por eso que estoy respondiendo esta pregunta.
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name' ,
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
Creo que este es el La forma más recomendada de hacer varias filas inserta más bien usando mysql_query. Porque cuando utilizamos un marco, es una buena práctica usar siempre las funciones incorporadas del marco. –
$query= array();
foreach($your_data as $row) {
$query[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $query));
use this in codeigniter for multiple data insertion
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name' ,
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
¿Y cómo es esto diferente de la respuesta de Somnath? De hecho, es una copia al carbón – asprin
He creado una clase que realiza múltiples líneas que se utiliza de la siguiente manera:
$pdo->beginTransaction();
$pmi = new PDOMultiLineInserter($pdo, "foo", array("a","b","c","e"), 10);
$pmi->insertRow($data);
// ....
$pmi->insertRow($data);
$pmi->purgeRemainingInserts();
$pdo->commit();
donde la clase se define como sigue:
class PDOMultiLineInserter {
private $_purgeAtCount;
private $_bigInsertQuery, $_singleInsertQuery;
private $_currentlyInsertingRows = array();
private $_currentlyInsertingCount = 0;
private $_numberOfFields;
private $_error;
private $_insertCount = 0;
/**
* Create a PDOMultiLine Insert object.
*
* @param PDO $pdo The PDO connection
* @param type $tableName The table name
* @param type $fieldsAsArray An array of the fields being inserted
* @param type $bigInsertCount How many rows to collect before performing an insert.
*/
function __construct(PDO $pdo, $tableName, $fieldsAsArray, $bigInsertCount = 100) {
$this->_numberOfFields = count($fieldsAsArray);
$insertIntoPortion = "REPLACE INTO `$tableName` (`".implode("`,`", $fieldsAsArray)."`) VALUES";
$questionMarks = " (?".str_repeat(",?", $this->_numberOfFields - 1).")";
$this->_purgeAtCount = $bigInsertCount;
$this->_bigInsertQuery = $pdo->prepare($insertIntoPortion.$questionMarks.str_repeat(", ".$questionMarks, $bigInsertCount - 1));
$this->_singleInsertQuery = $pdo->prepare($insertIntoPortion.$questionMarks);
}
function insertRow($rowData) {
// @todo Compare speed
// $this->_currentlyInsertingRows = array_merge($this->_currentlyInsertingRows, $rowData);
foreach($rowData as $v) array_push($this->_currentlyInsertingRows, $v);
//
if (++$this->_currentlyInsertingCount == $this->_purgeAtCount) {
if ($this->_bigInsertQuery->execute($this->_currentlyInsertingRows) === FALSE) {
$this->_error = "Failed to perform a multi-insert (after {$this->_insertCount} inserts), the following errors occurred:".implode('<br/>', $this->_bigInsertQuery->errorInfo());
return false;
}
$this->_insertCount++;
$this->_currentlyInsertingCount = 0;
$this->_currentlyInsertingRows = array();
}
return true;
}
function purgeRemainingInserts() {
while ($this->_currentlyInsertingCount > 0) {
$singleInsertData = array();
// @todo Compare speed - http://www.evardsson.com/blog/2010/02/05/comparing-php-array_shift-to-array_pop/
// for ($i = 0; $i < $this->_numberOfFields; $i++) $singleInsertData[] = array_pop($this->_currentlyInsertingRows); array_reverse($singleInsertData);
for ($i = 0; $i < $this->_numberOfFields; $i++) array_unshift($singleInsertData, array_pop($this->_currentlyInsertingRows));
if ($this->_singleInsertQuery->execute($singleInsertData) === FALSE) {
$this->_error = "Failed to perform a small-insert (whilst purging the remaining rows; the following errors occurred:".implode('<br/>', $this->_singleInsertQuery->errorInfo());
return false;
}
$this->_currentlyInsertingCount--;
}
}
public function getError() {
return $this->_error;
}
}
Utilice el lote de inserción en codeigniter para insertar varias filas de d ata
$this->db->insert_batch('tabname',$data_array); // $data_array holds the value to be inserted
Puedes hacerlo de varias formas en Codeigniter, p.
First By loop
foreach($myarray as $row)
{
$data = array("first"=>$row->first,"second"=>$row->sec);
$this->db->insert('table_name',$data);
}
Second -- By insert batch
$data = array(
array(
'first' => $myarray[0]['first'] ,
'second' => $myarray[0]['sec'],
),
array(
'first' => $myarray[1]['first'] ,
'second' => $myarray[1]['sec'],
),
);
$this->db->insert_batch('table_name', $data);
Third way -- By multiple value pass
$sql = array();
foreach($myarray as $row) {
$sql[] = '("'.mysql_real_escape_string($row['first']).'", '.$row['sec'].')';
}
mysql_query('INSERT INTO table (first, second) VALUES '.implode(',', $sql));
He creado esta función simple que ustedes pueden utilizar fácilmente. Tendrá que pasar el nombre de la tabla ($tbl)
, campo de tabla ($insertFieldsArr)
con sus datos de inserción, matriz de datos ($arr)
.
insert_batch('table',array('field1','field2'),$dataArray);
function insert_batch($tbl,$insertFieldsArr,$arr){ $sql = array();
foreach($arr as $row) {
$strVals='';
$cnt=0;
foreach($insertFieldsArr as $key=>$val){
if(is_array($row)){
$strVals.="'".mysql_real_escape_string($row[$cnt]).'\',';
}
else{
$strVals.="'".mysql_real_escape_string($row).'\',';
}
$cnt++;
}
$strVals=rtrim($strVals,',');
$sql[] = '('.$strVals.')';
}
$fields=implode(',',$insertFieldsArr);
mysql_query('INSERT INTO `'.$tbl.'` ('.$fields.') VALUES '.implode(',', $sql));
}
Aunque es demasiado tarde para responder esta pregunta. Aquí está mi respuesta sobre lo mismo.
Si está utilizando CodeIgniter, puede utilizar métodos incorporados definidos en la clase query_builder.
$ this-> db-> insert_batch()
genera una cadena de inserción sobre la base de los datos que proporcione, y se ejecuta la consulta. Puede pasar una matriz o un objeto a la función. Aquí hay un ejemplo usando una matriz:
$data = array(
array(
'title' => 'My title',
'name' => 'My Name',
'date' => 'My date'
),
array(
'title' => 'Another title',
'name' => 'Another Name',
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
El primer parámetro contendrá el nombre de la tabla, el segundo es una matriz asociativa de valores.
Puede encontrar más detalles sobre query_builder here
- 1. Insertar varias filas en MySQL
- 2. Insertar varias filas usando seleccionar
- 3. Insertar varias filas con una sola consulta
- 4. MySql - ¿Insertar varias filas con una subconsulta unida?
- 5. Insertar varias filas con una sola consulta MySQL
- 6. Insertar varias filas usando JdbcTemplate
- 7. Insertar varias filas en Oracle
- 8. php mysql_insert_id en varias filas?
- 9. Codeigniter Insertar varias filas en SQL
- 10. Cómo iterar por filas a través de una consulta de mysql en php
- 11. Cómo seleccionar varias filas de MySQL con una consulta y utilizarlos en php
- 12. Enviar una matriz multidimensional a través de POST con php
- 13. Insertar varias filas de valores por defecto en una tabla
- 14. MySQL ¿Cómo se INSERTAR EN una tabla con una subconsulta SELECT que devuelve varias filas?
- 15. Loop a través de una matriz php
- 16. PHP: ¿Insertar una referencia en una matriz?
- 17. Insertar varias filas en la tabla en SQL Server
- 18. ¿La mejor manera de insertar varias filas en Oracle?
- 19. SQL ¿Insertar una fila o varias filas de datos?
- 20. MySQL ON DUPLICATE KEY UPDATE para insertar varias filas en una sola consulta
- 21. Perl: actualizar varias filas con una llamada de MySQL
- 22. PHP MYSQL Insertar/Actualizar
- 23. SQL Server 2005: Insertar varias filas con una sola consulta
- 24. Obtener todas las filas seleccionadas de mysql en una matriz
- 25. Cómo insertar una matriz en una única declaración preparada de MySQL con PHP y PDO
- 26. Concatenar varias filas en filas individuales en MySQL
- 27. PHP/MySQL Insertar valores nulos
- 28. ¿actualizar varias filas usando límite en mysql?
- 29. Wrap leyenda horizontal a través de varias filas
- 30. inserta matriz php en mysql
he dado respuesta de acuerdo a su pregunta para insertar múltiples filas de CodeIgniter. –
@SomnathMuluk Gracias, sin embargo, hace tiempo que no necesito responder esta pregunta:) ... – toofarsideways
Recomendaría usar la función insert_batch de CodeIgniter. Si usa una biblioteca, siempre trate de aprovechar sus fortalezas y estándares de codificación. –