Php 如何使用CodeIgniter框架从数组中插入多行?

Php 如何使用CodeIgniter框架从数组中插入多行?,php,mysql,codeigniter,insert,bulkinsert,Php,Mysql,Codeigniter,Insert,Bulkinsert,我正在使用insert命令通过PHP将一个大数据集传递到一个MySQL表中,我想知道是否可以通过一个查询一次插入大约1000行,而不是将每个值附加到一英里长的字符串的末尾,然后执行它。我正在使用CodeIgniter框架,因此它的功能也对我可用。您可以使用mysqli_stmt类准备插入一行的查询,然后迭代数据数组。比如: $stmt = $db->stmt_init(); $stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, f

我正在使用insert命令通过PHP将一个大数据集传递到一个MySQL表中,我想知道是否可以通过一个查询一次插入大约1000行,而不是将每个值附加到一英里长的字符串的末尾,然后执行它。我正在使用CodeIgniter框架,因此它的功能也对我可用。

您可以使用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)

嗯,您不想执行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()

将内容转储到数组中一样简单。您可以始终使用mysql的
加载数据

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

执行批量插入而不是使用一堆
INSERT
语句。

在MySQL中,将一条
INSERT
语句与多行组合在一起比每行一条
INSERT
语句快得多

也就是说,听起来您可能在PHP中遇到了字符串处理问题,这实际上是一个算法问题,而不是语言问题。基本上,在处理大型字符串时,您希望尽量减少不必要的复制。这主要意味着您希望避免连接。构建大字符串(例如一次插入数百行)的最快和最有效的内存方法是利用
infrade()
函数和数组赋值

$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在
内爆()语句中执行一次。这是一个巨大的胜利


如果有很多列要放在一起,并且一个或多个列很长,那么还可以构建一个内部循环来完成同样的事情,并使用
infrade()
将values子句分配给外部数组。

PHP5中的mysqli是一个具有一些好函数的对象,可以让您加快上述答案的插入时间:

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

在插入许多行时关闭自动提交会大大加快插入速度,所以请关闭它,然后按上述方式执行,或者只创建一个字符串(sqlCombined),其中包含许多由分号分隔的插入语句,多查询可以很好地处理它们。

CodeIgniter现在支持多插入/批插入

$data=array(
排列(
“标题”=>“我的标题”,
'姓名'=>'我的姓名',
“日期”=>“我的日期”
),
排列(
“标题”=>“另一个标题”,
“名称”=>“另一个名称”,
“日期”=>“另一个日期”
)
);
$this->db->insert_batch('mytable',$data);
//生成:在mytable(标题、名称、日期)中插入值(“我的标题”、“我的名称”、“我的日期”)、(“另一个标题”、“另一个名称”、“另一个日期”)

我创建了一个类,该类执行多行操作,如下所示:

$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;
    }
}
其中,类别定义如下:

$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;
    }
}
类PDO多线程插入器{
私人$purgeAtCount;
私有$\u bigInsertQuery,$\u singleInsertQuery;
private$_currentlyInsertingRows=array();
private$\u currentlyInsertingCount=0;
私有$numberOfFields;
私有$u错误;
私有$_insertCount=0;
/**
*创建一个多行插入对象。
*
*@param PDO$PDO PDO连接
*@param type$tableName表名
*@param type$fieldsasrarray正在插入的字段数组
*@param type$biginsercount执行插入之前要收集的行数。
*/
函数u_构造(PDO$PDO,$tableName,$fieldsAsArray,$bigInsertCount=100){
$this->_numberofields=count($fieldsasrarray);
$INSERTINTOPTIONE=“替换为“$tableName”(`).introde(`,`,$fieldsasray)。“`)值”;
$questionMarks=“(?”.str\u repeat(“,?”,$this->\u numberOfFields-1”);
$this->\u purgeAtCount=$biginsercount;
$this->_bigInsertQuery=$pdo->prepare($insertintoint.$questionMarks.str_repeat(“,”$questionMarks,$biginsercount-1));
$this->_singleInsertQuery=$pdo->prepare($insertintopoint.$questionMarks);
}
函数insertRow($rowData){
//@todo比较速度
//$this->\u currentlyInsertingRows=array\u merge($this->\u currentlyInsertingRows,$rowData);
foreach($v为rowData)数组\u push($this->\u currentlyInsertingRows,$v);
//
如果(++$this->\u currentlyInsertingCount==$this->\u purgeAtCount){
如果($this->\u bigInsertQuery->execute($this->\u currentlyInsertingRows)==FALSE){
$this->_error=“未能执行多重插入(在{$this->_insertCount}插入之后),发生以下错误:“.inpolde('
',$this->_bigInsertQuery->errorInfo()); 返回false; } $this->_insertCount++; $this->_currentlyInsertingCount=0; $this->_currentlyInsertingRows=array(); } 返回true; } 函数purgeremaininginsert(){ 而($this->\u currentlyInsertingCount>0){ $singleInsertData=array(); //@todo比较速度-http://www.evardsson.com/blog/2010/02/05/comparing-php-array_shift-to-array_pop/ //对于($i=0;$i<$this->\u numberofields;$i++)$singleInsertData[]=array\u pop($this->\u currentlyInsertingRows);array\u reverse($singleInsertData); 对于($i=0;$i<$this->\u numberofields;$i++)数组\u unshift($singleInsertData,array\u pop($this->\u currentlyInsertingRows)); 如果($this->\u singleInsertQuery->execute($singleInsertData)==FALSE){ $this->\u error=“在清除其余行时执行小插入失败;出现以下错误:“.infrade(“
”,$this->\l”
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));
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));
}
$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')