insira várias linhas através de uma matriz php em mysql

Estou passando um grande dataset para uma tabela mysql através de php usando comandos de inserção e eu estou pensando se é possível inserir aproximadamente 1000 linhas ao mesmo tempo por meio de uma consulta além de acrescentar cada valor no final de uma string de uma milha longa e, em seguida, executando-o. Estou usando o framework codeigniter para que suas funções também estejam disponíveis para mim.

A assembly de uma instrução INSERT com várias linhas é muito mais rápida no MySQL do que uma instrução INSERT por linha.

Dito isto, parece que você pode estar executando problemas de manipulação de string em PHP, o que é realmente um problema de algoritmo, e não um idioma. Basicamente, ao trabalhar com cordas grandes, você deseja minimizar a cópia desnecessária. Principalmente, isso significa que você deseja evitar a concatenação. A maneira mais rápida e eficiente de memory para construir uma grande string, como para inserir centenas de linhas em uma, é aproveitar a function implode() e a atribuição da 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)); 

A vantagem desta abordagem é que você não copia e copia novamente a declaração SQL que você montou até agora com cada concatenação; Em vez disso, o PHP faz isso uma vez na declaração implode() . Esta é uma grande vitória.

Se você tem muitas colunas para juntar e uma ou mais são muito longas, você também pode criar um loop interno para fazer o mesmo e usar implode() para atribuir a cláusula de valores à matriz externa.

O inserto de inserção / lote múltiplo agora é suportado pelo codicador. Eu tive o mesmo problema. Embora seja muito tarde para responder a pergunta, isso ajudará alguém. É por isso que responde a esta pergunta.

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

Você poderia preparar a consulta para inserir uma linha usando a class mysqli_stmt e, em seguida, iterar sobre a matriz de dados. 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(); 

Onde ‘idsb’ são os tipos de dados que você está vinculando (int, double, string, blob).

Eu sei que esta é uma consulta antiga, mas eu estava apenas lendo e achava que eu acrescentaria o que encontrei em outro lugar:

mysqli no PHP 5 é um ojbect com algumas boas funções que lhe permitirão acelerar o tempo de inserção para a resposta acima:

 $mysqli->autocommit(FALSE); $mysqli->multi_query($sqlCombined); $mysqli->autocommit(TRUE); 

Desligar o autocommit ao inserir muitas linhas aumenta a velocidade de inserção, então desligue-o e, em seguida, execute como mencionado acima, ou apenas faça uma string (sqlCombined), que é muitas instruções de inserção separadas por pontos e vírgulas e multi-query irá lidar com eles.

Espero que isso ajude alguém a economizar tempo (procurando e inserindo!)

R

Você sempre pode usar o 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 fazer inserções em massa ao invés de usar um monte de instruções INSERT .

Bem, você não quer executar 1000 consultas de consulta, mas fazer isso está bem:

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

Dependendo da sua fonte de dados, preencher a matriz pode ser tão fácil como abrir um arquivo e despejar o conteúdo em uma matriz via file() .

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

Criei uma class que executa multi-line que é usada da seguinte maneira:

 $pdo->beginTransaction(); $pmi = new PDOMultiLineInserter($pdo, "foo", array("a","b","c","e"), 10); $pmi->insertRow($data); // .... $pmi->insertRow($data); $pmi->purgeRemainingInserts(); $pdo->commit(); 

onde a class é definida da seguinte forma:

 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('
', $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('
', $this->_singleInsertQuery->errorInfo()); return false; } $this->_currentlyInsertingCount--; } } public function getError() { return $this->_error; } }

Use o lote de inserção no codeigniter para inserir várias linhas de dados.

 $this->db->insert_batch('tabname',$data_array); // $data_array holds the value to be inserted 

Você pode fazê-lo com várias maneiras em codeigniter, por exemplo,

Primeiro por loop

 foreach($myarray as $row) { $data = array("first"=>$row->first,"second"=>$row->sec); $this->db->insert('table_name',$data); } 

Segundo – Por lote de inserção

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

Terceira via – Por passagem de valor múltiplo

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

Criei essa function simples que vocês podem usar facilmente. Você precisará passar o nome da tabela ($tbl) , campo de tabela ($insertFieldsArr) contra a sua inserção de dados, matriz de dados ($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)); } 

Embora seja tarde demais para responder a esta pergunta. Aqui está a minha resposta sobre o mesmo.

Se você estiver usando CodeIgniter, então você pode usar methods incorporados definidos na class query_builder.

$ this-> db-> insert_batch ()

Gera uma seqüência de inserção com base nos dados que você fornece e executa a consulta. Você pode passar uma matriz ou um object para a function. Aqui está um exemplo usando uma 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') 

O primeiro parâmetro conterá o nome da tabela, o segundo é uma matriz associativa de valores.

Você pode encontrar mais detalhes sobre query_builder aqui

 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') 
Intereting Posts