Weird insert behavior with mysql and codeginiter - php

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).

Related

How can I insert multiple values using a loop?

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");
}

Inserting thousands of rows in one query MySQL using PHP

I have tried whole day (again) but with error trying to insert in total of over billion of rows while inserting about 10k within one query. I want to use prepared statements to do this with MySQL, using innoDB tables. Hardware resources are not a problem, problem has all the time been indexing and one row / insert.
Do not say that I should use straight from list methods since I need to do some calculations before inserting. Input comes from file.
So I have a big while loop, looping text file lines and that's working fine.
I currently do it with inserting one per query.
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
$stmt->execute();
I have looked at examples doing it like so:
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?), (?, ?, ?) ..... ");
But I need to construct this to for like 5-10k rows for single query.
If someone has done something like this before, please give some reference to work with.
Thanks in advance!
The whole idea of a prepared query is that it reduces the overhead of setting up the query each time it's run – prepare once, execute repeatedly. That means there's not going to be a huge amount of difference (from the POV of the database) between running a prepared statement in a loop, or passing one giant query.
You don't include your whole code here, but an error that many people make is to include the statement preparation in the loop. Don't make that mistake! Something like this will be most efficient:
// these need a value before being used in bind_param
$str1 = $str2 = $str3 = "";
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute();
}
Though I always recommend using PDO prepared statements, as you get to avoid the potential mess of binding parameters:
// assuming $conn is a PDO object now
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute([$str1, $str2, $str3]);
}
Maybe because limit executing time from server. Try to use insert batch.
Add to array
$i = 0;
.. looping
$i++;
$mark[] = '(?,?,?)';
$val[] = $str1.",".$str2.",".$str3;
// check when 1k record
if($i == 1000){
$stmt = $conn->prepare("INSERT INTO ? (row1, row2, row3) VALUES ".implode(',', $mark);
$stmt->bind_param("sss", implode(',', $val));
$stmt->execute();
$mark = []; $val = []; $i = 0; // reset
}

Simple object sqli insert

Hello I'd like to insert all from $_SESSION into rows $key with value $value
so something like foreach ($_SESSION as $key => $value) {}
Imlooking at:Best way to INSERT many values in mysqli?
name of rows in mysqli is same as names of given $key .I need to insert each $value in its $key (row)
Code:
$query = "INSERT INTO testtable VALUES (?)";
$stmt = $dbc->prepare($query);
$stmt->bind_param("s", $key);
$mysqli->query("START TRANSACTION");
foreach ($_SESSION as $key => $value) {
$stmt->execute();
}
$stmt->close();
$mysqli->query("COMMIT");
Your query has a syntax error, which you never bothered checking for:
$query = "INSERT INTO testtable podatki VALUES (?)";
^^^^^^^^^^^^^^^^^
If that's really the table name, then it should be quoted with backticks:
$query = "INSERT INTO `testtable podatki` VALUES (?)";
^-----------------^
if podatki is a field name, then it should be
$query = "INSERT INTO testtable (podatki) VALUES (?)";
^-------^
And also never assume that a DB operation succeeded. ALWAYS check for errors:
$stmt = $dbc->prepare($query);
if (!$stmt) {
die(mysqli_error($dbc));
}
The error is saying that you are trying to call a member function, namely bind_param(), on a non-object.
That means that this line:
$stmt = $dbc->prepare($query);
is not succeeding,
and thus you have an incorrect return value that is set as the value of $stmt
so when you try to call bind_param it fails because $stmt is not the type of object that it was expecting.

PHP/mysql: mysqli prepared statement insert same value multiple times within for loop

I am using a prepared statement to insert multiple rows into a table using a for loop. What I require is for the same value ($id) to be inserted into all rows of the "id" column. Likewise, the timestamp should be inserted into the "submitted" column over all iterations.
My current code only inserts one column. Here is the code:
if($stmt = $link->prepare("INSERT INTO table (id, alt_ord, alt_id, rank, submitted) VALUES ($id,?,?,?, NOW())")){
$stmt->bind_param('iii', $q_ord, $q_ID, $rating);
for($i=0; $i < count($_POST['alt_ord']); $i++){
$q_ord = $_POST['alt_ord'][$i];
$q_ID = $_POST['alt_id'][$i];
$rating = $_POST['rank_'][$i];
$stmt->execute();
}
$stmt->close();
}
Using a combination of ?s with $id and NOW() in the INSERT statement is clearly incorrect. How would I repeat the ID and timestamp values in the insert as intended?
Assuming $id is an unknown value (from user input, etc), simply bind it along with the others and don't forget to check for errors
// make mysqli trigger useful errors (exceptions)
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$stmt = $link->prepare('INSERT INTO table (id, alt_ord, alt_id, rank, submitted) VALUES (?, ?, ?, ?, NOW())');
$stmt->bind_param('iiii', $id, $q_ord, $q_ID, $rating);
for ($i = 0; $i < count($_POST['alt_ord']); $i++) {
$q_ord = $_POST['alt_ord'][$i];
$q_ID = $_POST['alt_id'][$i];
$rating = $_POST['rank_'][$i]; // you sure about this one? "rank_"?
$stmt->execute();
}

Entering Values To DB With PDO With Foreach Loop

I am entering objects from an array into a database.
I have an array called $graphObject
I am looping through the array like this,
foreach($graphObject['tagged_places']->data as $data) {
}
Then I want to take each one of these values and enter them in to the mysql DB with PDO
$data->id
$data->created_time
$data->place->id
$data->place->location->latitude
$data->place->location->longitude
$data->place->name
I am confused on how to write this loop to enter each one of these fields foreach time a new field exist.
Assuming the DB connection is open and the fields in the DB are named
id created_time place_id latitude longitude name
How would I write this with PDO?
What you probably want to do is to build your insert in a loop and then simply execute a single insert statement. So something like this:
$sql = <<<EOT
INSERT INTO table (
`id`,
`created_time`,
`place_id`,
`latitude`,
`longitude`,
`name`)
VALUES
EOT;
foreach($graphObject['tagged_places']->data as $data) {
// add values into string you can remove single quotes if not needed
// (i.e. for numeric data types)
$values = <<<EOT
(
'{$data->id}',
'{$data->created_time}',
'{$data->place->id}',
'{$data->place->location->latitude}',
'{$data->place->location->longitude}',
'{$data->place->name}'
),
EOT;
$sql .= $values;
}
$sql = rtrim(',', $sql);
// execute query using $sql
// assume you have properly instantiated PDO object in $pdo
$result = $pdo->query($sql);
if (false === $result) {
// something went wrong, so log an error
// this assumes you have not configured PDO to throw exceptions
error_log(var_export($pdo->errorInfo(), true));
} else {
// continue doing whatever you want to do
}
Create a prepared statement:
$stmt = $db->prepare('
INSERT INTO table
(id, created_time, place_id, latitude, longitude, name)
VALUES
(?, ?, ?, ?, ?, ?)
');
Execute it on each loop
foreach($graphObject['tagged_places']->data as $data) {
$stmt->execute(array(
$data->id,
$data->created_time,
$data->place->id,
$data->place->location->latitude,
$data->place->location->longitude,
$data->place->name
));
}

Categories