вставьте несколько строк через массив php в mysql
Я передаю большой набор данных в таблицу MySQL через PHP с помощью команд вставки, и мне интересно, можно ли вставить около 1000 строк за раз с помощью запроса, отличного от добавления каждого значения в конце строки длиной в милю, а затем выполнить его. Я использую фреймворк Codeigniter, поэтому его функции также доступны для меня.
13 ответов:
монтаж одного
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()назначить п. значения в массив.
множественная вставка / пакетная вставка теперь поддерживается 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), которая представляет собой множество операторов вставки, разделенных точкой с запятой и мульти-запрос будет обрабатывать их нормально.
надеюсь, это поможет кому-то сэкономить время (поиск и установка!)
R
вы всегда можете использовать 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; } }
используйте insert batch в codeigniter для вставки нескольких строк данных.
$this->db->insert_batch('tabname',$data_array); // $data_array holds the value to be inserted
вы можете сделать это несколькими способами в codeigniter например
первый петли
foreach($myarray as $row) { $data = array("first"=>$row->first,"second"=>$row->sec); $this->db->insert('table_name',$data); }второй -- 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);Третий способ -- по нескольким значениям 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));
Я создал эту простую функцию, которые вы можете легко использовать. Вам нужно будет передать таблицу-name
($tbl), стола-поле($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')
Comments