it-swarm.com.ru

вставьте несколько строк через массив PHP в MySQL

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

121
toofarsideways

Сборка одного оператора 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 ​​внешнему массиву.

218
staticsan

Многократная вставка/пакетная вставка теперь поддерживается 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')
58
Somnath Muluk

Вы можете подготовить запрос для вставки одной строки с помощью класса 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). 

19
Espresso_Boy

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

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

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

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

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

Р

14
Ross Carver

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

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

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

7
vezult

Ну, вы не хотите выполнять 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().

5
bdl
$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));
3
Nikunj Dhimar

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

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

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

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

Первый По циклу

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));
0
Kumar Rakesh

Хотя уже поздно отвечать на этот вопрос. Вот мой ответ на тот же.

Если вы используете 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 здесь

0
Abhishek Singh

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

$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;
    }
}
0
user3682438