wstawianie wielu wierszy za pomocą tablicy php do mysql

Przekazuję duży zbiór danych do tabeli MySQL za pomocą PHP za pomocą poleceń insert i zastanawiam się, czy możliwe jest wstawianie około 1000 wierszy na raz za pomocą zapytania innego niż dołączanie każdej wartości na końcu ciągu o długości mili, a następnie jego wykonanie. Używam frameworka CodeIgniter, więc jego funkcje są również dostępne dla mnie.

Author: Danish Ali, 2009-04-23

13 answers

Złożenie jednej instrukcji INSERT z wieloma wierszami jest znacznie szybsze w MySQL niż jedna instrukcja INSERT na wiersz.

To powiedziawszy, wygląda na to, że możesz mieć problemy z obsługą łańcuchów w PHP, co tak naprawdę jest problemem algorytmów, a nie językowym. Zasadniczo, podczas pracy z dużymi strunami, chcesz zminimalizować niepotrzebne kopiowanie. Przede wszystkim oznacza to, że chcesz uniknąć konkatenacji. Najszybszy i najbardziej wydajny sposób na zbudowanie dużego ciągu, np. do wstawiania setki wierszy na jednym, jest skorzystanie z funkcji implode() i przypisania tablicy.

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

Zaletą tego podejścia jest to, że nie kopiujesz i nie kopiujesz instrukcji SQL, którą do tej pory zgromadziłeś przy każdej konkatenacji; zamiast tego PHP robi to raz w instrukcji implode(). To jest Wielkie zwycięstwo.

Jeśli masz wiele kolumn do złożenia, a jedna lub więcej są bardzo długie, możesz również zbudować wewnętrzną pętlę, aby zrobić to samo i użyć implode(), aby Przypisz klauzulę values do zewnętrznej tablicy.

 211
Author: staticsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 14:33:12

Multiple insert / batch insert jest teraz obsługiwany przez codeigniter. Miałem ten sam problem. Chociaż jest bardzo późno na odpowiedź na pytanie, to komuś pomoże. Dlatego odpowiadam na to pytanie.

$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')
 54
Author: Somnath Muluk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-21 12:41:04

Można przygotować zapytanie do wstawiania jednego wiersza za pomocą klasy mysqli_stmt, a następnie iterację nad tablicą danych. Coś w stylu:

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

Gdzie 'idsb' są typami danych, które chcesz powiązać (int, double, string, blob).

 15
Author: Espresso_Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-23 02:06:19

Wiem, że to stare zapytanie, ale właśnie czytałem i pomyślałem, że dodam to, co znalazłem gdzie indziej:

Mysqli w PHP 5 to ojbect z kilkoma dobrymi funkcjami, które pozwolą Ci przyspieszyć czas wstawiania odpowiedzi powyżej:

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

Wyłączenie autocommit podczas wstawiania wielu wierszy znacznie przyspiesza wstawianie, więc wyłącz go, a następnie wykonaj jak wspomniano powyżej, lub po prostu wykonaj łańcuch (sqlCombined), który jest wieloma instrukcjami insert oddzielonymi średnikami i wieloma zapytaniami. zajmij się nimi dobrze.

Mam nadzieję, że pomoże to komuś zaoszczędzić czas (wyszukiwanie i wstawianie!)

R

 13
Author: Ross Carver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-07 15:21:21

Zawsze możesz użyć 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' 

Do wykonywania masowych wstawek zamiast używania kilku INSERT instrukcji.

 7
Author: vezult,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-23 02:15:31

Cóż, nie chcesz wykonać 1000 zapytań, ale robienie tego jest w porządku:

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

W zależności od źródła danych, wypełnienie tablicy może być tak proste, jak otwarcie pliku i wrzucenie zawartości do tablicy za pomocą file().

 5
Author: bdl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-23 02:04:06
$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
Author: Nikunj Dhimar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-20 11:28:02

Stworzyłem klasę, która wykonuje multi-line, która jest używana w następujący sposób:

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

Gdzie klasa jest zdefiniowana następująco:

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
Author: user3682438,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 06:44:47

Użyj insert batch w codeigniter, aby wstawić wiele wierszy danych.

$this->db->insert_batch('tabname',$data_array); // $data_array holds the value to be inserted
 0
Author: aish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 11:46:16

Możesz to zrobić na kilka sposobów w codeigniter np.

First By loop

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

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

Third way -- by multiple value 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));
 0
Author: Kumar Rakesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 10:34:26

Stworzyłem tę prostą funkcję, z której możecie łatwo korzystać. Musisz podać nazwę tabeli ($tbl), pole table ($insertFieldsArr) przeciwko wstawianiu danych, tablica danych ($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
Author: Waqas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-14 14:51:57

Chociaż jest już za późno, aby odpowiedzieć na to pytanie. Oto moja odpowiedź na to samo.

Jeśli używasz CodeIgniter, możesz użyć wbudowanych metod zdefiniowanych w klasie query_builder.

$this - > db- > insert_batch()

Generuje łańcuch wstawiania na podstawie dostarczonych danych i uruchamia zapytanie. Do funkcji można przekazać tablicę lub obiekt. Oto przykład użycia tablicy:

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

Pierwszy parametr będzie zawierał nazwa tabeli, Druga to asocjacyjna tablica wartości.

Więcej informacji na temat query_builder znajdziesz tutaj
 0
Author: Abhishek Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-16 13:04:32
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')
 -3
Author: Manas Mittal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-13 12:33:32