it-swarm.com.de

flüge mehrere Zeilen über ein PHP-Array in mysql ein

Ich übergebe eine große Datenmenge in eine MySQL-Tabelle über PHP mit Einfügungsbefehlen. Ich frage mich, ob es möglich ist, ungefähr 1000 Zeilen gleichzeitig über eine andere Abfrage einzufügen, als jeden Wert am Ende einer Meile anzufügen lange Zeichenfolge und dann ausführen. Ich verwende das CodeIgniter-Framework, so dass mir auch seine Funktionen zur Verfügung stehen.

121
toofarsideways

Das Zusammenstellen einer INSERT-Anweisung mit mehreren Zeilen ist in MySQL viel schneller als eine INSERT-Anweisung pro Zeile.

Das klingt jedoch so, als ob Sie in PHP auf String-Handling-Probleme stoßen, was eigentlich ein Algorithmusproblem ist, kein Sprachproblem. Grundsätzlich möchten Sie beim Arbeiten mit großen Zeichenfolgen das unnötige Kopieren minimieren. In erster Linie bedeutet dies, dass Sie die Verkettung vermeiden möchten. Die schnellste und speichereffizienteste Methode zum Erstellen einer großen Zeichenfolge, z. B. zum Einfügen von Hunderten von Zeilen in eine Zeile, besteht darin, die Funktion implode() und die Array-Zuordnung zu nutzen.

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

Der Vorteil dieses Ansatzes ist, dass Sie die SQL-Anweisung, die Sie bisher mit jeder Verkettung zusammengestellt haben, nicht kopieren und erneut kopieren. Stattdessen führt PHP dies einmal in der implode()-Anweisung aus. Dies ist ein großer Gewinn.

Wenn Sie viele Spalten zusammenstellen müssen und eine oder mehrere sehr lang sind, können Sie auch eine innere Schleife erstellen, um dasselbe zu tun, und mit implode() die Werteklausel dem äußeren Array zuweisen.

218
staticsan

Mehrere Einfügungen/Stapeleinfügungen werden jetzt von Codeigniter unterstützt. Ich hatte das gleiche Problem. Obwohl es für die Beantwortung der Frage sehr spät ist, wird es jemandem helfen. Deshalb beantworte ich diese Frage.

$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

Sie können die Abfrage mit der Klasse mysqli_stmt für das Einfügen einer Zeile vorbereiten und dann das Datenarray durchlaufen. So etwas wie:

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

Dabei sind 'idsb' die Datentypen, die Sie binden (int, double, string, blob). 

19
Espresso_Boy

Ich weiß, das ist eine alte Frage, aber ich habe gerade gelesen und dachte, ich würde hinzufügen, was ich woanders gefunden habe:

mysqli in PHP 5 ist ein Ojbect mit einigen guten Funktionen, mit denen Sie die Einfügungszeit für die Antwort oben beschleunigen können:

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

Durch das Deaktivieren von Autocommit beim Einfügen vieler Zeilen wird das Einfügen erheblich beschleunigt. Deaktivieren Sie es dann, führen Sie es wie oben erwähnt aus oder erstellen Sie einfach einen String (sqlCombined), der viele durch Semikolons getrennte Einfüge-Anweisungen enthält.

Hoffe, das hilft jemandem, Zeit zu sparen (Suchen und Einfügen!)

R

14
Ross Carver

Sie könnten immer den LOAD DATA von mysql verwenden:

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

masseneinfügungen statt mehrere INSERT-Anweisungen zu verwenden.

7
vezult

Nun, Sie möchten nicht 1000 Abfrageaufrufe ausführen, aber dies ist in Ordnung:

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

Das Auffüllen des Arrays kann je nach Datenquelle so einfach sein wie das Öffnen einer Datei und das Ablegen des Inhalts über file() in ein Array.

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

Ich habe diese einfache Funktion erstellt, die Sie leicht verwenden können. Sie müssen den Tabellennamen ($tbl), Tabellenfeld ($insertFieldsArr) an Ihre Einfügungsdaten, Datenfeld ($arr) übergeben.

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

Verwenden Sie den Einfüge-Stapel in Codeigniter, um mehrere Datenzeilen einzufügen.

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

Sie können dies auf verschiedene Arten in Codeigniter tun, z.

Erste By-Schleife

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

Zweitens - Durch Batch einfügen

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

Dritter Weg - Durch mehrfache Wertübergabe

$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

Obwohl es zu spät ist, diese Frage zu beantworten. Hier ist meine Antwort auf dasselbe.

Wenn Sie CodeIgniter verwenden, können Sie eingebaute Methoden verwenden, die in der query_builder-Klasse definiert sind.

$ this-> db-> insert_batch ()

Erzeugt eine Einfügungszeichenfolge basierend auf den von Ihnen gelieferten Daten und führt die Abfrage aus. Sie können der Funktion entweder ein Array oder ein Objekt übergeben. Hier ist ein Beispiel mit einem Array:

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

Der erste Parameter enthält den Tabellennamen, der zweite ist ein assoziatives Array von Werten.

Sie finden weitere Details zu query_builder hier

0
Abhishek Singh

Ich habe eine Klasse erstellt, die mehrzeilig ausgeführt wird und wie folgt verwendet wird:

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

wo die Klasse wie folgt definiert ist:

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