вставьте несколько строк через массив PHP в MySQL - PullRequest
125 голосов
/ 23 апреля 2009

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

Ответы [ 13 ]

224 голосов
/ 23 апреля 2009

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

59 голосов
/ 21 марта 2012

Множественная вставка / пакетная вставка теперь поддерживаются 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')
19 голосов
/ 23 апреля 2009

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

14 голосов
/ 07 марта 2011

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

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

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

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

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

R

7 голосов
/ 23 апреля 2009

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

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

для массовых вставок вместо использования INSERT операторов.

5 голосов
/ 23 апреля 2009

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

3 голосов
/ 20 июля 2013
$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));
1 голос
/ 22 августа 2016

Вы можете сделать это несколькими способами в 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 голосов
/ 16 апреля 2017

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

Если вы используете 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 голосов
/ 14 декабря 2016

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