Here is my code:
$post_id = 10;
$tags_id = [23, 55, 155, 15];
$stmt = $dbh_conn->prepare("INSERT INTO post_tags (post_id, tag_id) VALUES (?, ?)");
$stmt->execute([$post_id, $tags_id[0]]);
if ( !$stmt->rowCount() ){
throwErrorMessage("Something went wrong while inserting tags");
}
As you can see, my code only inserts one row. I can count the number of count($tags_id) and copy-paste the whole code according to that number. But that approach doesn't seem good to me. Any idea what's the best approach to use an loop on that?
Prepare once and insert in a loop:
$stmt = $dbh_conn->prepare("INSERT INTO post_tags (post_id, tag_id) VALUES (?, ?)");
foreach ($tags_id as $tag) {
$stmt->execute([$post_id, $tag]);
if ( !$stmt->rowCount() ){
throwErrorMessage("Something went wrong while inserting tag " . $tag);
}
}
You can either…
A) use a single statement and produce the VALUES (…) part in side a loop.
$values = [];
foreach ($tags_id as $tag) {
$values[] = sprintf( '(%d, %s)', (int)$post_id, $dbh_conn->quote($tag) );
}
$stmt = $dbh_conn->prepare(
sprintf(
'INSERT INTO post_tags (post_id, tag_id) VALUES %s;',
implode(',', $values)
));
if(!$stmt->execute()) {
// something went wrong
}
or
B) re-use the statement for one row per INSERT and call the execute inside a loop. (as suggested in the other answers)
Prepare the insert query and execute once. Try below code, it might be help
$post_id = 10;
$tags_id = [23, 55, 155, 15];
$lastElement = end($tags_id);
$insert = "INSERT INTO post_tags (post_id, tag_id) VALUES";
foreach ($tags_id as $key => $value)
{
if ($value == $lastElement) {
$insert .= "(".$post_id.", ".$value.")";
} else {
$insert .= "(".$post_id.", ".$value."),";
}
}
$stmt = $dbh_conn->prepare($insert);
$stmt->execute();
if ( !$stmt->rowCount() ){
throwErrorMessage("Something went wrong while inserting tags");
}
Related
I have a form something like below:
<input name="first_name[]" type="text">
<input name="last_name[]" type="text">
<input name="email[]" type="email">
I am using while loop to print/echo number of groups of above form fields it required.
There will be multiple data in it, i'm not understanding how use insert query to insert data in mysql table using php.
First, you will need to know how many records you are trying to insert. I used first_name for this, but you could use any of them. (I am assuming since these are grouped together that you will always have the same number of first_name, last_name, and email.):
$count = count($_POST['first_name']);
After you know that, you can build an SQL statement that will insert all of the records in one query:
$sql = "INSERT INTO people (first_name, last_name, email) VALUES ";
$sql .= implode(', ', array_fill(0, $count, '(?, ?, ?)'));
The second line (implode...) will create sets of placeholders in the statement for each record you are trying to insert. (The three question marks represent the three columns you are inserting.) For example, if you had two field groups, the statement would look like:
INSERT INTO people (first_name, last_name, email) VALUES (?, ?, ?), (?, ?, ?)
After you have created the SQL string, you can create a new PDO connection and use that connection to create a prepared statement using your SQL.
$pdo = new PDO($dsn, $user, $password);
$statement = $pdo->prepare($sql);
Next you need to bind your values to the prepared statement. There are various different ways to do this. Here is one example:
// Create a multidimensional array using each of the fields from your field groups
$columns = array($_POST['first_name'], $_POST['last_name'], $_POST['email']);
$index = 1; // This is the index of the placeholder in the prepared statement
for ($i=0; $i < $count; $i++) { // This will loop as many times as you have field groups
$row = array_column($columns, $i);
// using array_column will pull everything from the $i index of each of the sub-arrays
// e.g. first_name[$i], last_name[$i], email[$i]
foreach ($row as $value) {
// bind the value and increment the index
$statement->bindValue($index, $value);
$index++;
}
}
After you have bound all the parameters, you can execute the prepared statement:
$statement->execute();
You can try something like this (you can find comments in the code):
if (isset($_POST['yourSubmitButton']) && isset($_POST['first_name'])) {
try {
$conn = new PDO("mysql:host=localhost;dbname=mysql", 'db_username', 'db_password');
}
catch(PDOException $e) {
echo $e->getMessage();
die();
}
$sql = 'INSERT INTO your_table (first_name, last_name, email) VALUES ';
$sql_append = array(); //Here we have the placeholder to be inserted
$binds = array(); //Here he have the values for the placeholders
for($i = 0; $i < count($_POST['first_name']); $i++) {
if (!( isset($_POST['first_name'][$i]) && isset($_POST['last_name'][$i]) && isset($_POST['email'][$i]) )) {
//We need all the values to be valid
continue;
}
//Add the placeholders and bind values
$sql_append[] = '(first_name = :first_name'.$i.', last_name = :last_name'.$i.', email = :email'.$i.')';
$binds[':first_name'.$i] = $_POST['first_name'][$i];
$binds[':last_name'.$i] = $_POST['last_name'][$i];
$binds[':email'.$i] = $_POST['email'][$i];
}
//Implode and add to the query and then execute
$sql = $sql.implode(', ', $sql_append).';';
$stmt = $conn->prepare($sql);
$stmt->execute($binds);
}
If you have 2 rows $sql will have:
echo $sql;
Result:
INSERT INTO your_table (first_name, last_name, email) VALUES (first_name = :first_name0, last_name = :last_name0, email = :email0), (first_name = :first_name1, last_name = :last_name1, email = :email1);
Ok so I execute the following code for inserting data into database:
$db_conn->beginTransaction();
$query = $db_conn->prepare('INSERT INTO mytable(name, user) VALUES(:name, :user)');
foreach($UploadData AS $DataValue)
{
$query->execute(array(':name' => $DataValue['Name'],':user' =>$_SESSION['user']));
}
$db_conn->commit();
Now in this code block execute() runs 100s time if I have that much data. Like before I use to do with basic mysqli concatenation and executes the query only once.
Will that can be done here with PDO also?
$SQL = 'INSERT INTO mytable (name, user) VALUES';
foreach( $UploadData AS $DataValue)
$SQL .= sprintf(" ( '%s', '%s' ),", $DataValue['Name'], $DataValue['user'] );
$SQL = substr($SQL, -1);
$query = $db_conn->prepare($SQL);
$query->execute();
Result
INSERT INTO mytable (name, user) VALUES ('VAL', 'VAL'), ('VAL', 'VAL') ....
I am trying to insert multiple rows based on a loop.
This code inserts the first item from the loop only, then ignores the rest of the loop
I know the loop is counting correctly as echo'ing out the values outputs ok
$i = 1;
while ($i <= $count){
foreach($html->find('.markuptag a') as $mystring){
if(preg_match_all("|<a.*(?=href=\"([^\"]*)\")[^>]*>([^<]*)</a>|i", $mystring, $matches)){
$a = $matches[2][0];
}
$query = "INSERT INTO mytable (`firstname`, `lastname`, `var_a`) VALUES ('$fistname', '$lastname', '$a')";
$mysqli->query($query);//<< is there a better way?
}
$i++;
}
Build an array of the rows to insert, then insert them all at once. Something like this:
$arr = []; // array() in PHP 5.3 and older
foreach(...) {
...
$arr[] = "('$fistname', '$lastname', '$a')";
}
$mysqli->query("INSERT INTO mytable (`firstname`, `lastname`, `var_a`) VALUES "
.implode(",",$arr));
I have a foreach statement looping through JSON data and inserting the contents into MySQL. I want to skip the insert if a specific username is shown for $author string. Is the below method ok or is it better to handle at the database level?
foreach ($response['data'] as $data) {
$id = $data['id'];
$created_time = $data['created_time'];
$thumbnail = $data['images']['low_resolution']['url'];
$author = $data['user']['username'];
$caption = mysql_real_escape_string($data['caption']['text']);
$link = $data['link'];
$likes = $data['likes']['count'];
if ($author == 'USERNAME') {
mysql_close($con);
} else {
$query = "INSERT IGNORE INTO pbr (id, created_time, thumbnail, author, caption, link, likes, hash) VALUES ('$id', '$created_time', '$thumbnail', '$author', '$caption', '$link', '$likes', '$hash')";
$result = mysql_query($query) or die(mysql_error());
mysql_close($con);
}
}
Why closing SQL connection at each loop iteration?
Why not simply do:
if ($author == 'USERNAME')
continue; // next iteration
$query = "INSERT IGNORE INTO pbr (id, created_time, thumbnail, author, caption, link, likes, hash)
VALUES ('$id', '$created_time', '$thumbnail', '$author', '$caption', '$link', '$likes', '$hash')";
$result = mysql_query($query) or die(mysql_error());
BTW you should bind parameters to your queries, or at least use mysql_real_escape_string() otherwise will have problems with values containing quotes (currently, you only do it for variable $caption, I guess that $link, $thumbnail and $username can contain single quotes as well).
I have a fairly simple insert statement
<...>
if (!empty($attributes)) {
$sql = 'INSERT INTO `part_attrs` (`part_id`, `attr`, `type`, `list_order`) VALUES (?, ?, ?, ?)';
foreach($attributes as $key => $attribute) {
$this->db->query($sql, array($partid, $attribute[0], $attribute[1], $key));
$attrid = $this->db->insert_id();
echo $attrid.'<br />';
if (strlen($attribute[2]) > 0) {
$values = explode(',', $attribute[2]);
$sql = 'INSERT INTO `attr_values` (`attr_id`, `field_values`) VALUES (?, ?)';
foreach ($values as $value) {
$this->db->query($sql, array($attrid, trim($value)));
}
}
}
}
<...>
The odd thing is only one or two of the rows are being inserted. I put that echo line in to see the row id's it was returning for each insert since I'm not getting any errors. If for example I insert three items it will return something like 18, 124, 128. Where the 18 id is the next and expected id so this row gets inserted and then the rest don't. Any ideas what might be wrong?
You are changing the value of $sql inside your second if statement. 124 and 128 is attributes from the attr_values table. Consider using another variable name inside your if statement, or move the first assignment to $sql inside the foreach loop (move it down one line).