PHP Procedural Prepared Statement for Mysqli Multi Query - php

I have a PHP code that opens a CSV file using fgetcsv then reads through each rows then constructs a "Insert Into" query and attaches it to a variable named $MyQuery. This is the most understandable way for me when trying to update my database using information from a CSV file downloaded from the company website. This is working as I expected using the code below:
if (mysqli_multi_query($conn, $MyQuery))
{
do
{
/* store first result set */
if ($result = mysqli_store_result($conn))
{
mysqli_free_result($result);
}
} while (mysqli_next_result($conn));
}
Recently I learned about Prepared Statements and how they can secure your queries.
PROBLEM: How can I do multiquery with prepared statement in Procedural Mysqli way? I tried researching, a lot says it isn't possible. Some say it is possible but by creating different variables for each queries which is impossible for me as I will be inserting over 10000 records to my database from the CSV file. Is there any other ways to achieve this?
I'm thinking it can be done by looping through each records then doing a prepared-statement version of Insert Into but I thought doing 10000 Insert Into SQL commands would be very slow.

I am not 100% sure what you are asking but fallowing might work. First of all I would use pdo for connecting to a database. Fallowing is just a basic outline of what I think you want to do.
$pdo = new PDO('mysql:host=localhost;dbname=mydatabase', 'myusername', 'mypassowrd');
$query = "
INSERT INTO table (colum1, colum2, colum3)
VALUES (:info1, :info2, :info3)
";
$stmt = $pdo->prepare($query);
do
{
$stmt->execute(array(':info1'=>$my_info1, ':info2'=>$my_info2, ':info3'=>$my_info3));
} while( your condition);
There is two advantages for prepared statements. First is security and the second allows to do the same query over and over changing the values. This will make each of queries fast if you prepare them.
here is a ling that can explain more about prepared statements
http://php.net/manual/en/pdo.prepared-statements.php
I am adding a Procedural way of doing it using mysqli.
$query = "
INSERT INTO table (colum1, colum2, colum3)
VALUES (?, ?, ?)
";
if ($stmt = mysqli_prepare($conn, $query))
{
do
{
mysqli_stmt_bind_param($stmt, "sss", $my_info1, $my_info2, $my_info3);
mysqli_stmt_execute($stmt);
} while( your condition)
}
I am not sure why you are using mysqli_store_result(), mysqli_free_result(), or mysqli_next_result(). Since inserting rows produces no results.

Related

Rolling out prepared statements using bind_result & fetch

I am in the process of migrating to php7 & msqli. I have a lot of old php files that will need prepared statements using bind_result & fetch. Thus, before I modify all these files I want to be sure I am coding prepared statements properly using bind_result & fetch, such that they are reasonably safe from sql injection. The code in my example works for me (binds & fetches properly), but I just want to be sure I coded them safely. I am still learning to code prepared statements for other implementations as well.
I also tried get_result instead of bind_result, but for my purposes (db interactions) I believe bind_result will suffice.
Here is the example of a php file that I will be using as the template for all my other php files that will need to be modified with prepared statements using bind_result & fetch:
<?php
//mysqli object oriented - bind_result prepared statement
//connect to database
require 'con_db.php';
//prepare, bind_result and fetch
$stmt = $con->prepare("SELECT image, caption FROM tblimages
WHERE tblimages.catID = 6 ORDER by imageID");
$stmt->execute();
$stmt->bind_result($image, $caption);
while ($stmt->fetch()) {
echo "{$image} <br> {$caption} <br> <br>";
}
$stmt->close();
//close connection
mysqli_close($con);
?>
And here is the php file that makes the db connection via "require", i.e. con_db.php:
<?php
//mysqli object oriented connect to db
//MySQL errors get transferred into PHP exceptions in error log
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
//establish connection, any connection errors go to php.errors
$con = new mysqli('localhost','uid','pw',
'db');
?>
I'm hoping I coded the prepared statements in a reasonably secure fashion to prevent sql injection. But any comments or suggestions are welcome. Thank you.
UPDATE: I decided to show (below) an example of the current code I was going to modify with prepared statements (with the bind_result, fetch example above). So below is a representation of the majority of php/mysqli code that currently exists that lives in many php files that would need to be modified. It is the existing mysql SELECT statements that vary the most. However, based on the feedback I have received I believe since there are no variables being passed there is no reason to use prepared statements with binding. However, I DO have some forms that DO pass variables (GET & POST), and I will modify those php files using prepared statements (bind_param, bind_result & fetch). I hope that made sense :-) I just thought it would be more useful to show an example of the code I originally was planning to modify since I may not need to modify much of it based on feedback I have received here, plus what I have read since my original post (on my concern re: sql injection). But please feel free to correct me if I'm wrong. Thank you.
<?php
//mysqli object oriented - mysqli_query & mysqli_fetch_array
//connect to database
require 'con_db.php';
//query and fetch
$result = mysqli_query($con,"SELECT image, caption FROM
tblimages WHERE tblimages.catid = 1");
while($row = mysqli_fetch_array($result))
{
echo $row['image'];
echo "<br />";
echo $row['caption'];
echo "<br />";
}
mysqli_close($con);
?>
You don't actually need bind_result() and fetch().
With PHP7, almost certainly you will have get_result() that will give you a familiar resource-type variable from which you can get the familiar array.
$stmt = $con->prepare("SELECT image, caption FROM tblimages
WHERE catID = 6 ORDER by imageID");
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
echo "{$row['image']} <br> {$row['caption']} <br> <br>";
}
so you can keep a lot of your old code intact.
A couple notes:
Like #Dharman said, you don't really need a prepare/bind/execute routine if no placeholder marks are used i the query.
Like #Dharman said, better try PDO instead, it is much easier to use.
That said, you can greatly reduce the overhead with a simple mysqli helper function. Instead of writing this monster of a code (let's pretend the id in the query is dynamical)
$sql = "SELECT image, caption FROM tblimages WHERE catID = ? ORDER by imageID";
$stmt = $con->prepare($sql);
$stmt->bind_param("s", $catId);
$stmt->execute();
$res = $stmt->get_result();
you can have it in just two lines:
$sql = "SELECT image, caption FROM tblimages WHERE catID = ? ORDER by imageID";
$res = mysqli_select($con, $sql, [$id]);

PHP Insert Into Error

I am started to learn coding start with HTML, CSS, and php. I created a basic form to test my skill. However, I got stuck with this. Can you help me on that?
I know that it is open to SQL injections, I am just trying to improve myself in coding and will use prepared statements and parameterized queries in real life.
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$mysql_host = "";
$mysql_username = "";
$mysql_password = "";
$mysql_database = "";
$conn = new mysqli ($mysql_host, $mysql_username, $mysql_password, $mysql_database);
$c_name = $_POST["club_name"];
$c_league = $_POST["league"];
$c_rank = $_POST["ranking"];
$c_prank = $_POST["previous_rank"];
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES ('$c_name', '$c_league, $c_rank, $c_prank);";
mysqli_query($conn, $sql);
if ($conn->query($sql) === TRUE) {
echo "kayit islendi";
}
else {
echo "Error". $sql ."<br>". $conn->error;
}
$conn->close();
}
?>
Everytime I used the form I got this error.
ErrorINSERT INTO... etc.
You are missing quotes around your insert values, here's the fixed sql:
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES ('$c_name', '$c_league', '$c_rank', '$c_prank');"
You were missing quotes around each value!
HOWEVER, this is an ill advised way of making database queries in production. Either use mysqli_real_escape_string to sanitize your strings(each of your variables will need this treatment) or use prepared statements.
Alternatively, and the way you should always use your DB is via the PDO wrapper. In this case you would use: PDO::quote. PDO offers a unified interface to the most popular databases there are. Here you can read more about PDO: http://php.net/manual/en/book.pdo.php
Coders prefer prepared statements to sanitizing their input. However this incurs extra communication with the mysql server vs writing a bit more code in php. Prepared statements are more involved then normal queries as they are cached on the SQL server and preprocessed waiting for data to be used, also having a miriad of question marks makes the code very hard to read especially if you start working in production and have a miriad of columns to fill. Here you can read more about the prepared statements:
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
Main takeaway:
never, EVER, EVER save unsanitized data to the DB!!Use mysqli_real_escape_string or PDO::quote or prepared statements, depending on situation.
use prepared statements for what they have been created for not just as a wholesale sanitizer tool, use them when you have to execute the same query repeatedly. Especially if this query is not an insert in which case I suggest you do mass insert like so:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9); read more here: https://dev.mysql.com/doc/refman/5.7/en/insert.html This has a caveat in that the maximum size of the sql with inserted values should never be larger then max_allowed_packet config.
You should use prepared statements. Not only does it prevent SQL injection attacks, it also avoids the pesky quoting issues you are currently facing
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES (?, ?, ?, ?);";
$result = $conn->prepare($sql);
$result->bind_param('ssss', $c_name, $c_league, $c_rank, $c_prank);
echo $result->execute() === true ? 'kayit islendi' : 'Error'.$conn->error;

How to minify an INSERT and PRINT query?

I have two PHP/SQL functions and I am wondering how I would minify them. I'd like to run the 3 insert commands as a single $import rather than three, but I am not sure how to minify it.
$import9="INSERT into wp_postmeta (meta_id,post_id,meta_key,meta_value) values(',','$data[37]','lower_electric_costs','$data[5]')";
$import10="INSERT into wp_postmeta (meta_id,post_id,meta_key,meta_value) values(',','$data[37]','cheapest_green_electric','$data[6]')";
$import11="INSERT into wp_postmeta (meta_id,post_id,meta_key,meta_value) values(',','$data[37]','contract_type','$data[11]')";
Its the same thing with my PRINT results - how would I minify this down?
mysql_query($import9) or die("mysql_error()");
print $import9."<br>";
mysql_query($import10) or die("mysql_error()");
print $import10."<br>";
mysql_query($import11) or die("mysql_error()");
print $import11."<br>";
I am still learning PHP/SQL and learning how to minify my code is an important part of it I think. If someone can just how me an example of what a minified version would look like, then I can probably take it from there.
Thanks
You could combine it into a single query as follows:
$import9="
INSERT into
wp_postmeta
(meta_id,post_id,meta_key,meta_value)
values
(',','$data[37]','lower_electric_costs','$data[5]'),
(',','$data[37]','cheapest_green_electric','$data[6]'),
(',','$data[37]','contract_type','$data[11]')
";
However, you should use mysqli instead of mysql functions, as mysql functions are deprecated.
mysqli_query($import9);
It is also advised that you do not use INSERT queries with mysqli_query but rather use Prepared Statements for security reasons. You should check out PDO and Prepared Statements.
First, create a PDO instance.
$db = new PDO("mysql:host=localhost;port=3306;dbname=mydb", "username", "password");
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //Turn off prepared statement emulation too.
With a prepared statement, you would prepare your statement with the server:
$stmt = $db->prepare("
INSERT into
wp_postmeta
(meta_id,post_id,meta_key,meta_value)
values
(?,?,?,?)
");
With an array like:
$values = array(
array(',',$data[37], 'lower_electric_costs', $data[5]),
array(',',$data[37], 'cheapest_green_electric', $data[6]),
array(',',$data[37], 'contract_type', $data[11]),
);
Next, you'd issue a series of execute statements:
foreach ($values as $v) {
$stmt->execute($v);
}
Finally, close the statement so that more statements can be executed:
$stmt->closeCursor();

multi query with prepared statements

I am trying understand how multi queries work in mysqli. But I confess that is not easy to understand.
Basically how I can do these queries in a multi query? The page doesn't talk about prepared statements in multi queries.
($sql = $db -> prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)"));
$sql -> bind_param('sss', $name, $email, $hash);
$sql -> execute();
($sq = $db -> prepare("INSERT INTO activation_link_password_reset (activation_link) VALUES (?)"));
$sq -> bind_param('s', $linkHash);
$sq -> execute();
You can't use prepared statements there, and the speedup is also negligible, so go for the easier to debug seperate queries.
If you really want to do it in 1 call with prepared statements, create a PROCEDURE (even more difficult to debug...), and prepare CALL(:param1,:param2);.
I actually just figured this out a few days ago. The move to MySQLi is not a trivial one but ill go ahead and show you the query loop for prepared statements.
$db = new mysqli(...)
$statement = $db->prepare('SELECT count(*) as [hitchhikers] FROM `T_Users` WHERE `id` > ? AND `signin` like ?');
$statement->bind_param("ss", 42, '%adams');
if ($statement->execute())
{
$statement->store_result();
$statement->bind_result($hitchhikers);
$statement->fetch();
// do something with hitchhikers here
}
else
{
// there was a problem with the execution, check $db->error
}
$statement->close();
$db->next_result();
Everything here works similar to the non oo format by replacing -> with _ and passing the returned value into the new function, but this process here is pretty much what you should look to be doing with each of those statements. You can abstract it away with a mysqli wrapper class as well.
After the $db->next_result() call you are able to repeat the process again. This change has to do with the way the MySQL connection and results are handled with MySQLi. You can, of course, avoid this issue entirely by switching back to mysql_ queries and resources.
Specifically for multi_query, you separate your queries with a semicolon, in a single string. The example you linked to shows how to process the results.
MySQLi Book #PHP.net

uploadify php mysql - bulk upload and bulk insert

I am using uploadify to upload pictures into server . Back end I am using PHP script . In PHP script I am inserting the file location and some other details in database in addition to copying to target location .
Problem :- If I am uploading 20 files , the PHP script is getting called 20 times and the database insert statement are getting called 20 times to insert for different images . Definitely calling database 20 times is inefficient way of doing it . Is there any way I can hold the file names( and location) and call the insert statement (in the end) only once to insert all the 20 records at once ?
Thanks for your help
Regards
Kiran
One approach I recommend for this is the use of a prepared statement through the mysqli extension. To quote on the main advantage:
The actual purpose to use a prepared
statement in sql is to cut the cost of
processing queries; NOT to separate
data from query. That's how it's being
used w/ php NOW, not how it was
designed to be used in the first
place. With SQL you cut the cost of
executing multiple similar queries
down by using a prepared statement..
Doing so cuts out the parsing,
validation and most often generates an
execution plan for said query up
front. Which is why they run faster in
a loop, than their IMMEDIATE Query
cousins do.
Source: http://us2.php.net/manual/en/mysqli.prepare.php#103730
To give an example on how you can utilize this:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
if ($stmt = $mysqli->prepare("INSERT INTO `images` (`location`, `size`, `othervalues`) VALUES(?, ?, ?)")) {
foreach($images as $image) {
// s = string value
// i = integer value
$stmt->bind_param("sis", $image['location'], $image['size'], $image['othervalues']);
$stmt->execute();
}
$stmt->close();
}
// Your prepared statement failed, handle the error
else {
}
$mysqli->close();
I'd recommend reading up on mysqli::prepare and mysqli_stmt::bind_param for more information on how the process works. I also recommend reading up on prepared statements in the MySQL documentation.

Categories