Скажем, у нас есть несколько строк, которые нужно вставить в таблицу:
$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, что разница производительности не будет замечена в подавляющем большинстве реализаций.
Я сделал бы это первым способом, подготовил оператор с одной строкой замещающих параметров и вставлял бы одну строку за раз с выполнением.
$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.