вставить несколько строк через php-массив в mysql

Я передаю большой набор данных в таблицу mysql через php, используя команды вставки, и мне интересно, можно ли вставлять примерно 1000 строк за один раз с помощью запроса, отличного от добавления каждого значения в конце строки длиной в милю, а затем выполняя его. Я использую фреймворк codeigniter, поэтому его функции также доступны мне.

Сборка одного оператора INSERT с несколькими строками в MySQL намного быстрее, чем один оператор INSERT каждой строки.

Тем не менее, похоже, что вы можете столкнуться с проблемами обработки строк в PHP, что является проблемой алгоритма, а не языковой. В основном, при работе с большими строками вы хотите минимизировать ненужное копирование. Прежде всего, это означает, что вы хотите избежать конкатенации. Самый быстрый и наиболее эффективный способ создания большой строки, например, для вставки сотен строк в один, заключается в использовании функции implode() и назначения массива.

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

Преимущество такого подхода заключается в том, что вы не копируете и не копируете инструкцию SQL, которую вы собрали до сих пор с каждой конкатенацией; вместо этого PHP делает это один раз в инструкции implode() . Это большая победа.

Если у вас есть много столбцов для объединения, и один или несколько из них очень длинные, вы также можете построить внутренний цикл, чтобы сделать то же самое, и использовать implode() чтобы назначить предложение values ​​внешнему массиву.

Несколько вставных / пакетных вставок теперь поддерживаются с помощью codeigniter. У меня была такая же проблема. Хотя ответить на вопрос очень поздно, это поможет кому-то. Вот почему ответ на этот вопрос.

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

Вы можете подготовить запрос для вставки одной строки с использованием класса mysqli_stmt, а затем выполнить итерацию по массиву данных. Что-то вроде:

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

Где «idsb» – это типы данных, которые вы связываете (int, double, string, blob).

Я знаю, что это старый запрос, но я просто читал и думал, что добавлю то, что нашел в другом месте:

mysqli в PHP 5 – это ojbect с некоторыми хорошими функциями, которые позволят вам ускорить время ввода для ответа выше:

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

Отключение автосочетания при вставке многих строк значительно ускоряет вставку, поэтому отключите его, затем выполните, как указано выше, или просто создайте строку (sqlCombined), в которую входят многие вставные операторы, разделенные полуколониями, и многопроцессор будет обрабатывать их отлично.

Надеюсь, это поможет кому-то сэкономить время (поиск и вставка!)

р

Вы всегда можете использовать mysql LOAD DATA :

 LOAD DATA LOCAL INFILE '/full/path/to/file/foo.csv' INTO TABLE `footable` FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n' 

делать объемные вставки, а не использовать кучу INSERT .

Ну, вы не хотите выполнять 1000 запросов, но это нормально:

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

В зависимости от вашего источника данных, заполнение массива может быть таким же простым, как открытие файла и сброс содержимого в массив через 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)); 

Я создал класс, который выполняет многострочную линию, которая используется следующим образом:

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

где класс определяется следующим образом:

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

Используйте вставную партию в codeigniter для вставки нескольких строк данных.

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

Вы можете сделать это несколькими способами в кодеиндикторе, например

Первый цикл

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

Второй – с помощью вставки

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

Третий путь – через несколько значений

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

Я создал эту простую функцию, которую вы, ребята, можете легко использовать. Вам нужно будет передать имя таблицы ($tbl) , table-field ($insertFieldsArr) против ваших данных вставки, массива данных ($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)); } 

Хотя ответить на этот вопрос слишком поздно. Вот мой ответ на то же самое.

Если вы используете CodeIgniter, вы можете использовать встроенные методы, определенные в классе query_builder.

$ this-> db-> insert_batch ()

Создает строку вставки на основе данных, которые вы поставляете, и запускает запрос. Вы можете передать массив или объект функции. Вот пример использования массива:

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

Первый параметр будет содержать имя таблицы, второй – ассоциативный массив значений.

Вы можете найти более подробную информацию о query_builder здесь

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