繁体   English   中英

在PHP PDO MYSQL中插入多行的最佳方法是什么?

[英]What is the best way to insert multiple rows in PHP PDO MYSQL?

假设我们要在表格中插入多行:

$rows = [(1,2,3), (4,5,6), (7,8,9) ... ] //[ array of values ];

使用PDO:

$sql = "insert into `table_name` (col1, col2, col3) values (?, ?, ?)" ;

现在,您应该如何继续插入行? 像这样?

$stmt = $db->prepare($sql);

foreach($rows as $row){
  $stmt->execute($row);
}

还是像这样?

$sql = "insert into `table_name` (col1, col2, col3) values ";
$sql .= //not sure the best way to concatenate all the values, use implode?
$db->prepare($sql)->execute();

哪种方法更快更安全? 插入多行的最佳方法是什么?

您至少有以下两个选择:

$rows = [(1,2,3), (4,5,6), (7,8,9) ... ];

$sql = "insert into `table_name` (col1, col2, col3) values (?,?,?)";

$stmt = $db->prepare($sql);

foreach($rows as $row)
{
    $stmt->execute($row);
}

OR:

$rows = [(1,2,3), (4,5,6), (7,8,9) ... ];

$sql = "insert into `table_name` (col1, col2, col3) values ";

$paramArray = array();

$sqlArray = array();

foreach($rows as $row)
{
    $sqlArray[] = '(' . implode(',', array_fill(0, count($row), '?')) . ')';

    foreach($row as $element)
    {
        $paramArray[] = $element;
    }
}

// $sqlArray will look like: ["(?,?,?)", "(?,?,?)", ... ]

// Your $paramArray will basically be a flattened version of $rows.

$sql .= implode(',', $sqlArray);

$stmt = $db->prepare($sql);

$stmt->execute($paramArray);

如您所见,第一个版本具有许多简单的代码; 但是第二个版本确实执行了批量插入。 批处理插入应该更快,但是我同意@BillKarwin的观点 ,在绝大多数实现中性能差异不会被注意到。

我将以第一种方式进行操作,使用一行参数占位符准备语句,然后使用execute一次插入一行。

$stmt = $db->prepare($sql);

foreach($rows as $row){
    $stmt-> execute($row);
}

它的速度不像在单个插入中执行多行那样快,但是它足够接近以至于您可能永远不会注意到差异。

这样做的好处是,使用代码非常容易。 这就是为什么无论如何都使用PHP,以提高开发人员的效率,而不是运行时的效率。

如果您有许多行(数百行或数千行),并且性能是优先事项,则应考虑使用LOAD DATA INFILE

您也可以这样:

<?php
$qmarks = '(?,?,?)'. str_repeat(',(?,?,?)', count($rows)-1);

$sql = "INSERT INTO `table`(col1,col2,col3) VALUES $qmarks";
$vals = array();
foreach($rows as $row)
    $vals = array_merge($vals, $row);
$db->prepare($sql)->execute($vals);

老实说,我不知道哪一个会更快,这完全取决于mysql和php服务器之间的延迟。

/* test.php */

<?php
require_once('Database.php');

$obj = new Database();
$table = "test";

$rows = array(
    array(
    'name' => 'balasubramani',
    'status' => 1
    ),
    array(
    'name' => 'balakumar',
    'status' => 1
    ),
    array(
    'name' => 'mani',
    'status' => 1
    )
);

var_dump($obj->insertMultiple($table,$rows));
?>

/* Database.php */
<?php
class Database 
{

    /* Initializing Database Information */

    var $host = 'localhost';
    var $user = 'root';
    var $pass = '';
    var $database = "database";
    var $dbh;

    /* Connecting Datbase */

    public function __construct(){
        try {
            $this->dbh = new PDO('mysql:host='.$this->host.';dbname='.$this->database.'', $this->user, $this->pass);
            //print "Connected Successfully";
        } 
        catch (PDOException $e) {
            print "Error!: " . $e->getMessage() . "<br/>";
            die();
        }
    }
/* Insert Multiple Rows in a table */

    public function insertMultiple($table,$rows){

        $this->dbh->beginTransaction(); // also helps speed up your inserts.
        $insert_values = array();
        foreach($rows as $d){
            $question_marks[] = '('  . $this->placeholders('?', sizeof($d)) . ')';
            $insert_values = array_merge($insert_values, array_values($d));
            $datafields = array_keys($d);
        }

        $sql = "INSERT INTO $table (" . implode(",", $datafields ) . ") VALUES " . implode(',', $question_marks);

        $stmt = $this->dbh->prepare ($sql);
        try {
            $stmt->execute($insert_values);
        } catch (PDOException $e){
            echo $e->getMessage();
        }
        return $this->dbh->commit();
    }

    /*  placeholders for prepared statements like (?,?,?)  */

    function placeholders($text, $count=0, $separator=","){
        $result = array();
        if($count > 0){
            for($x=0; $x<$count; $x++){
                $result[] = $text;
            }
        }

        return implode($separator, $result);
    }

}
?>

上面的代码应该是使用PDO插入多个记录的良好解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM