php - multidimensional - insertar varios registros en sql
insertar mĂșltiples filas a travĂ©s de una matriz php en mysql (13)
Aunque es demasiado tarde para responder a esta pregunta. Aquí está mi respuesta sobre lo mismo.
Si está utilizando CodeIgniter, puede usar métodos incorporados definidos en la clase query_builder.
$ this-> db-> insert_batch ()
Genera una cadena de inserción basada en los datos que proporciona y 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
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 agregar cada valor al final de una cadena de una milla de largo y luego ejecutándolo. Estoy usando el marco codeigniter por lo que sus funciones también están disponibles para mí.
Bueno, no quieres ejecutar 1000 llamadas de consulta, pero hacer esto está 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 puede ser tan fácil como abrir un archivo y volcar los contenidos en una matriz a través de un file()
.
Creé esta sencilla función que ustedes pueden usar fácilmente. Tendrá que pasar el nombre de la tabla ($tbl)
, el campo de la tabla ($insertFieldsArr)
contra su información 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));
}
Creé una clase que realiza múltiples líneas que se usa 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 de la siguiente manera:
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;
}
}
La inserción múltiple de inserción / lote ahora es compatible con 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'')
Puede preparar la consulta para insertar una fila usando la clase mysqli_stmt, y luego iterar sobre la matriz de datos. Algo 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 datos que está vinculando (int, double, string, blob).
Puedes hacerlo de varias maneras en codeigniter, por ejemplo
First By loop
foreach($myarray as $row)
{
$data = array("first"=>$row->first,"second"=>$row->sec);
$this->db->insert(''table_name'',$data);
}
Segundo : por lote de inserción
$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);
Tercera forma: por pase de valor múltiple
$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));
Sé que esta es una consulta antigua, pero solo estaba leyendo y pensé que agregaría lo que encontré en otra parte:
mysqli en PHP 5 es un ojbect con algunas buenas funciones que te permitirán acelerar el tiempo de inserción de la respuesta anterior:
$mysqli->autocommit(FALSE);
$mysqli->multi_query($sqlCombined);
$mysqli->autocommit(TRUE);
Desactivar la confirmación automática al insertar muchas filas acelera la inserción, así que desactívela, luego ejecute como se mencionó anteriormente, o simplemente haga una cadena (sqlCombined) que es muchas instrucciones insertadas separadas por punto y coma y multi-query las manejará bien.
Espero que esto ayude a alguien a ahorrar tiempo (¡buscando e insertando!)
R
Siempre puedes usar LOAD DATA
mysql:
LOAD DATA LOCAL INFILE ''/full/path/to/file/foo.csv'' INTO TABLE `footable` FIELDS TERMINATED BY '','' LINES TERMINATED BY ''/r/n''
para hacer inserciones masivas en lugar de usar un montón de INSERT
.
Use Insertar lote en codeigniter para insertar múltiples filas de datos.
$this->db->insert_batch(''tabname'',$data_array); // $data_array holds the value to be inserted
Ensamblar una INSERT
con varias filas es mucho más rápido en MySQL que una INSERT
por fila.
Dicho esto, parece que podría encontrarse con problemas de manejo de cadenas en PHP, que en realidad es 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 manera más rápida y más eficiente desde el punto de vista de la memoria de construir una cadena grande, como para 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 vuelve a copiar la instrucción SQL que ha ensamblado hasta el momento con cada concatenación; en cambio, PHP hace esto una vez en la instrucción implode()
. Esta es una gran victoria.
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.
$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'')