PHP/MySQL INSERT same data INTO two Tables - php

I have two forms that share some same columns: NAME, EMAIL, NOMINEE, DEPT, RANK and TIMESTAMP
and I want to store those same columns in a new table called: TEACHING_AWARD_ALL_NOMINATIONS.
I have came up with the code to store each data into different table and then there should be some code to store the shared columns into TEACHING_AWARD_ALL_NOMINATIONS table.
I haven't came up with the code yet, please help!!!!
$srr = array_map('mysql_escape_string', $_REQUEST);
if ($srr['NOMINATIONTYPE'] == 'STUDENT')
$fields = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'COURSE', 'YEARTERM', 'REQUIRED_FOR_MAJOR', 'MAJOR_LEARNING_OBJECTIVES', 'WHAT_EXTENT_INSTRUCTOR_HELP', 'RANK', 'RANK_COMMENT', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3', 'TEXTBOX_4', 'TEXTBOX_5');
else if ($srr['NOMINATIONTYPE'] == 'FACULTY')
$fields = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'RANK', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3');
else die('error: no nomination type');
foreach ($fields as $f)
$$f = $srr[$f];
$qry = "INSERT INTO TEACHING_AWARD_".$srr['NOMINATIONTYPE']."_NOMINATIONS (";
foreach ($fields as $f) $qry .= $f . ", ";
$qry = substr($qry, 0, -2);
$qry .= ") VALUES (";
foreach ($fields as $f) $qry .= "'" . $$f . "', ";
$qry = substr($qry, 0, -2);
$qry .= ")";
$result = mysql_query($qry) or die('An error ocurred: '.mysql_error());
echo 'Success! Thank you for submitting your nomination.';

WARNING! As noted in comments your original code is using deprecated functions and suffers from potential security issues.
Check out the refactored solution that is using PDO, and yes you
should use PDO too (instead of your current approach).
Check out the code below, untested but should do your job. As written above it uses PDO - check the docs here
// obviously, first set your connection parameters $DbHost, $DbName etc.
//connect to mysql
$dbh = new PDO("mysql:host=".$DbHost.";dbname=".$DbName, $DbUser, $DbPass, array(PDO::ATTR_PERSISTENT => true));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->query('SET NAMES UTF8'); //assuming you use utf-8 encoding
//provide values array
$values = $YourValuesArray;
//set field types
$fields = array();
$fieldsStudent = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'COURSE', 'YEARTERM', 'REQUIRED_FOR_MAJOR', 'MAJOR_LEARNING_OBJECTIVES', 'WHAT_EXTENT_INSTRUCTOR_HELP', 'RANK', 'RANK_COMMENT', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3', 'TEXTBOX_4', 'TEXTBOX_5');
$fieldsFaculty = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'RANK', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3');
$fieldsAll = array_intersect($fieldsStudent, $fieldsFaculty);
//pick the proper field set or die
$fields = ($srr['NOMINATIONTYPE'] == 'STUDENT') ? $fieldsStudent : $fieldsFaculty;
if(empty($fields)) die('error: no nomination type');
//set tables
$table = 'TEACHING_AWARD_'.$srr['NOMINATIONTYPE'].'_NOMINATIONS';
$tableAll = 'TEACHING_AWARD_ALL_NOMINATIONS';
//construct fields string
$strFields = implode(",", $fields);
$strFieldsAll = implode(",", $fieldsAll);
//construct the placeholders string
$strIns = implode(",", array_map(function($item){ return ":".$item; }, $fields));
$strInsAll = implode(",", array_map(function($item){ return ":".$item; }, $fieldsAll));
//insert specific data
$sql = "INSERT INTO $table ($strFields) VALUES ($strIns)";
$sth = $dbh->prepare($sql);
//bind values to placeholders
foreach ($fields as $f)
{
$sth->bindValue(':' . $f, $values[$f]);
}
$sth->execute();
//insert all data
$sql = "INSERT INTO $tableAll ($strFieldsAll) VALUES ($strInsAll)";
$sth = $dbh->prepare($sql);
//bind values to placeholders
foreach ($fieldsAll as $f)
{
$sth->bindValue(':' . $f, $values[$f]);
}
$sth->execute();
EDIT:
As per your comment, to select a UNIONed set of results using PDO you can use the below (untested) code:
//connect to mysql
$dbh = new PDO("mysql:host=".$DbHost.";dbname=".$DbName, $DbUser, $DbPass, array(PDO::ATTR_PERSISTENT => true));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->query('SET NAMES UTF8'); //assuming you use utf-8 encoding
$sql = "SELECT NAME, EMAIL, NOMINEE, DEPT, RANK, TIMESTAMP, 'STUDENT' AS TYPE FROM TEACHING_AWARD_STUDENT_NOMINATIONS
UNION
SELECT NAME, EMAIL, NOMINEE, DEPT, RANK, TIMESTAMP, 'FACULTY' AS TYPE FROM TEACHING_AWARD_FACULTY_NOMINATIONS";
$sth = $dbh->prepare($sql);
$sth->execute();
//init result array
$results = array();
//fetch the results into an array
while($row = $sth->fetch(PDO::FETCH_ASSOC))
$results[] = $row;
//show results or do whatever else you need
print_r($results);

You could try making two arrays, one for the "shared" columns (NAME, EMAIL, etc.) and another for the "type-specific" columns (COURSE, YEARTERM, etc.). Then, when you are building up your SQL statement, do a foreach on the "shared" columns followed immediately by the "type-specific" columns to simulate the entire table. It might look something like this:
$qry = "INSERT INTO TEACHING_AWARD_".$srr['NOMINATIONTYPE']."_NOMINATIONS (";
foreach ($fields_shared as $f) $qry .= $f . ", ";
foreach ($fields_typespecific as $f) $qry .= $f . ", ";
$qry = substr($qry, 0, -2);
$qry .= ") VALUES (";
foreach ($fields_shared as $f) $qry .= "'" . $$f . "', ";
foreach ($fields_typespecific as $f) $qry .= "'" . $$f . "', ";
$qry = substr($qry, 0, -2);
$qry .= ")";
I would also agree with th3falc0n's comment about looking into preparing your SQL statements with more robust tools.
Another consideration: rather than enter redundant data into a TEACHING_AWARD_ALL_NOMINATIONS table, why not simply make that a view that pulls all shared columns from each type-specific table (likely using a UNION statement)? This prevents redundant data and would make data maintenance easier (e.g. when a nomination is deleted from one of the type-specific table, it automatically vanishes from the ALL_NOMINATIONS view, etc.).

Related

PDO bindParam() Multiple insert foreach [duplicate]

Say, we have multiple rows to be inserted in a table:
$rows = [(1,2,3), (4,5,6), (7,8,9) ... ] //[ array of values ];
Using PDO:
$sql = "insert into `table_name` (col1, col2, col3) values (?, ?, ?)" ;
Now, how should you proceed in inserting the rows? Like this?
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt->execute($row);
}
or, like this?
$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();
Which way would be faster and safer? What is the best way to insert multiple rows?
You have at least these two options:
$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);
As you can see the first version features a lot simpler code; however the second version does execute a batch insert. The batch insert should be faster, but I agree with #BillKarwin that the performance difference will not be noticed in the vast majority of implementations.
I would do it the first way, prepare the statement with one row of parameter placeholders, and insert one row at a time with execute.
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt-> execute($row);
}
It's not quite as fast as doing multiple rows in a single insert, but it's close enough that you will probably never notice the difference.
And this has the advantage that it's very easy to work with the code. That's why you're using PHP anyway, for the developer efficiency, not the runtime efficiency.
If you have many rows (hundreds or thousands), and performance is a priority, you should consider using LOAD DATA INFILE.
You can also go this way:
<?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);
To be honest, I don't know which one will be faster, all depends on the delay between mysql and the php server.
/* 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);
}
}
?>
The above code should be good solution for Inserting Multiple Records using PDO.

Parsing bulk Mysql Insert PHP [duplicate]

Say, we have multiple rows to be inserted in a table:
$rows = [(1,2,3), (4,5,6), (7,8,9) ... ] //[ array of values ];
Using PDO:
$sql = "insert into `table_name` (col1, col2, col3) values (?, ?, ?)" ;
Now, how should you proceed in inserting the rows? Like this?
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt->execute($row);
}
or, like this?
$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();
Which way would be faster and safer? What is the best way to insert multiple rows?
You have at least these two options:
$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);
As you can see the first version features a lot simpler code; however the second version does execute a batch insert. The batch insert should be faster, but I agree with #BillKarwin that the performance difference will not be noticed in the vast majority of implementations.
I would do it the first way, prepare the statement with one row of parameter placeholders, and insert one row at a time with execute.
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt-> execute($row);
}
It's not quite as fast as doing multiple rows in a single insert, but it's close enough that you will probably never notice the difference.
And this has the advantage that it's very easy to work with the code. That's why you're using PHP anyway, for the developer efficiency, not the runtime efficiency.
If you have many rows (hundreds or thousands), and performance is a priority, you should consider using LOAD DATA INFILE.
You can also go this way:
<?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);
To be honest, I don't know which one will be faster, all depends on the delay between mysql and the php server.
/* 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);
}
}
?>
The above code should be good solution for Inserting Multiple Records using PDO.

MySQL inserting thorough an array

I have a MySQL table called season
I'm getting data from a PostgreSQL then store it inside my array and then i use the implode function to pass the data stored inside the array:
$season = array(
'asset_id' => $asset_id,
'number' => $season_number
);
$season_col = implode(', ', array_keys($season));
$season_values = implode(', ', array_values($season));
Then I insert:
$insert_season = mysqli_query($conn, "INSERT INTO season(".$season_col.") VALUES(".$season_values.")");
This is one of 6 tables where i'm inserting data, and the problem is that when I run the code it does not insert all the data at once, I have to reload the page several times before it's all inserted.
I also must add that the tables are all Interconnected with foreign keys, and also i tried disable the foreign key check and it did nothing for me.
I also do a check in php for repeated and nonexistent data:
$check_for_season = mysqli_query($conn, "SELECT asset_id, number FROM season WHERE asset_id = ".$asset_id." AND number = ".$season_number." LIMIT 1");
if (mysqli_fetch_array($check_for_season)) {
echo "Updates data";
} else {
$insert_season = mysqli_query($conn, "INSERT INTO season(".$season_col.") VALUES(".$season_values.")");
}
}
My educated guess would be that you encounter SQL error mid-execution could be due one of table's columns defined not to except certain values like 'NOT NULL' for instance. the execution would terminate if you try to pass $season['number'] = '';
Try to check SQL errors in your mysqli object.
Also try to wrap your values in quotes.
$season_values = implode("','", array_values($season));
$insert_season = mysqli_query($conn, "INSERT INTO season(".$season_col.") VALUES('".$season_values."')");
to avoid errors when passing empty values.
You can use this code to dynamically create query.
$conn = new PDO('mysql:host=' . $HOST . ';dbname=' . $DATABASE, $USERNAME, $PASSWORD);
$conn->exec("set names utf8");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$ins_query = 'INSERT INTO `' . $table_name . '` ';
$columns = array();
$columns_bindings = array();
foreach ($dataArray as $column_name => $data) {
$columns[] = $column_name;
$columns_bindings[] = ':' . $column_name;
}
$ins_query = $ins_query . '(' . implode(', ', $columns) . ') VALUES (' . implode(', ', $columns_bindings) . ')';
$stmt = $conn->prepare($ins_query);
foreach ($dataArray as $column_name => $data) {
$stmt->bindValue(":" . $column_name, $data);
}
if (!$stmt->execute()) {
print_r($stmt->errorInfo());
} else {
echo "Insertd";
}

How to insert multiple record using PHP MySQL and PDO? [duplicate]

Say, we have multiple rows to be inserted in a table:
$rows = [(1,2,3), (4,5,6), (7,8,9) ... ] //[ array of values ];
Using PDO:
$sql = "insert into `table_name` (col1, col2, col3) values (?, ?, ?)" ;
Now, how should you proceed in inserting the rows? Like this?
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt->execute($row);
}
or, like this?
$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();
Which way would be faster and safer? What is the best way to insert multiple rows?
You have at least these two options:
$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);
As you can see the first version features a lot simpler code; however the second version does execute a batch insert. The batch insert should be faster, but I agree with #BillKarwin that the performance difference will not be noticed in the vast majority of implementations.
I would do it the first way, prepare the statement with one row of parameter placeholders, and insert one row at a time with execute.
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt-> execute($row);
}
It's not quite as fast as doing multiple rows in a single insert, but it's close enough that you will probably never notice the difference.
And this has the advantage that it's very easy to work with the code. That's why you're using PHP anyway, for the developer efficiency, not the runtime efficiency.
If you have many rows (hundreds or thousands), and performance is a priority, you should consider using LOAD DATA INFILE.
You can also go this way:
<?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);
To be honest, I don't know which one will be faster, all depends on the delay between mysql and the php server.
/* 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);
}
}
?>
The above code should be good solution for Inserting Multiple Records using PDO.

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

Say, we have multiple rows to be inserted in a table:
$rows = [(1,2,3), (4,5,6), (7,8,9) ... ] //[ array of values ];
Using PDO:
$sql = "insert into `table_name` (col1, col2, col3) values (?, ?, ?)" ;
Now, how should you proceed in inserting the rows? Like this?
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt->execute($row);
}
or, like this?
$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();
Which way would be faster and safer? What is the best way to insert multiple rows?
You have at least these two options:
$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);
As you can see the first version features a lot simpler code; however the second version does execute a batch insert. The batch insert should be faster, but I agree with #BillKarwin that the performance difference will not be noticed in the vast majority of implementations.
I would do it the first way, prepare the statement with one row of parameter placeholders, and insert one row at a time with execute.
$stmt = $db->prepare($sql);
foreach($rows as $row){
$stmt-> execute($row);
}
It's not quite as fast as doing multiple rows in a single insert, but it's close enough that you will probably never notice the difference.
And this has the advantage that it's very easy to work with the code. That's why you're using PHP anyway, for the developer efficiency, not the runtime efficiency.
If you have many rows (hundreds or thousands), and performance is a priority, you should consider using LOAD DATA INFILE.
You can also go this way:
<?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);
To be honest, I don't know which one will be faster, all depends on the delay between mysql and the php server.
/* 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);
}
}
?>
The above code should be good solution for Inserting Multiple Records using PDO.

Categories