When to close prepared statements in PHP?
Example:
$query = "insert into web_reviews (title,added_date,reviewer_home_url,read_more_link,summary) values(?,?,?,?,?)";
$stmt = $this->db->prepare($query);
$stmt->bind_params($this->title,$this->added_date,$this->reviewer_home_url,$this->read_more,$this->summary);
$stmt->execute() or die("Cannot add the date to the database, please try again.");
$stmt->close();
$stmt = $this->db->prepare("select id from web_reviews where title = ? and read_more = ?");
$stmt->bind_params($this->title,$this->read_more);
$stmt->execute();
$stmt->bind_results($web_review_id);
$stmt->close();
Should I use $stmt->close(); here?
Edit:
What is written on the PHP Manual and also one comment from the manual says:
Closes a prepared statement.
mysqli_stmt_close() also deallocates
the statement handle. If the current
statement has pending or unread
results, this function cancels them so
that the next query can be executed.
Comment:
if you are repeating an statement in
an loop using bind_param and so on
inside it for a larger operation. i
thougt id would be good to clean it
with stmt->close. but it broke always
with an error after aprox. 250
operations . As i tried it with
stmt->reset it worked for me.
That is a good use of close, especially since you are planning on making another query. With both PDO statements and MySQLi statements, I find that erring on the side of cleanliness is almost always for the best -- it removes potential bugs down the line.
As to the gentlemen with 250 operations... I don't see what the real use case is. Why does he need to query the database 250 different times? Why can't he query the database once with 250 records? Or, more likely, why can't he query the database 25 times with 10 records?
I am unable to comment currently, so I am just providing an answer. When you run a prepared statement that queries the database for a result, it will not execute another query unless you remove the current result it is storing. $result = $stmt->get_result().
Secondly, If you will need the result from the first query to be saved so that you use it later, then I recommend using two result sets. The first stores the result from the first execution of $stmt and the second for the second execution. This might not answer the question directly, but it may help someone.
Related
I am trying to remove running MySQL queries in for loops inside some code.
But I am not sure how best to achieve that.
using PHP PDO, with named parameters, how do I store the queries and then run them as a batch after the loop? so the only thing that happens in the for loop is the queries get built, but not executed until after the loop has finished?
here is example code:
for($i=$rowcount; $i>0; $i--){
$id = $array[$i];
$query = "DELETE FROM table WHERE ID=:id AND Order=:order";
$stmt = $conn->prepare($query);
$stmt->execute(array('id' => $id, 'order' => $i));
}
My initial reaction would be: Why do this? What is your motivation? Simply avoiding SQL in loops, or do you have some sort of operational problems you want to avoid?
Your exact query would not be that easy to convert into a single query because you do have tuples of ID and Order values that have to match in order to be deleted. Also notice that prepared statements usually do not accept an arbitrary number of parameters, so even if you'd be able to transform your query into the form DELETE FROM table WHERE (ID=1 AND Order=1000) OR (ID=4 AND Order=1234)..., you'd have to somehow work out how to fill the first, second, third ... placeholder. Additionally, you'd be forced to generate that prepared statement dynamically, which is probably the opposite of how prepared statements should be done when it comes to security.
If you have performance problems because deleting 1000 entries one after the other has a big impact, there are alternatives: If you wrap the deletion inside one single transaction, then it probably doesn't matter that much how many entries you delete - ALL of them will be deleted once the transaction is committed. Also note that using prepared statements is one way to speed up database operations - but only if you prepare them only once before you loop, and inside the loop you'd only pass new parameters again and again.
So to wrap it up: Undoing SQL in loops is not the best thing if the programming problem you want to solve is better solved using a loop, and there is no other problem related to it. If however there is such a problem, it has to be analyzed and mentioned - removing the loops isn't an automatic success story.
I suppose you need to ensure that all queries are executed, in other words you need a transaction:
$conn->beginTransaction();
try{
$query = "DELETE FROM table WHERE ID=:id AND Order=:order";
$stmt = $conn->prepare($query);
for($i=$rowcount;$i>0;$i--){
$id = $array[$i];
$stmt->execute(['id' => $id,'order'=>$i]);
}
$conn->commit();
}
catch(Exception $ex){
$conn->rollBack();
}
I'm working on an application at the moment that uses PDO with a MySQL database.
I'm seeing some queries, which are just very simple SELECT statements, e.g.
SELECT * FROM table ORDER BY name ASC
The code does not use prepare, for example:
$sql = "SELECT * FROM " . $this->table . " ORDER BY name ASC";
$stmt = $this->db->query($sql);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
Is it ok to do this, i.e. without using prepare, if there's no placeholders in the query?
The reason I've asked this is because according to the documentation it says
The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers
which makes me wonder why you'd use this in the case of having no (zero) parameter markers?
Yes, because the use of prepared statements have 2 main causes:
Enhance running the same query with different parameters.
Prevent sql injection by separating sql code from the parameters.
Since you have no parameters that could be handled by a prepared statement (table names cannot be a parameter), you do not gain anything by pushing the query through as a prepared statement.
You still need to make sure that whatever is returned by $this->table will not cause any issues with the generated sql code.
Of course you can omit prepare if there is no dynamic data in your query.
But prepared statements have more advantages than only securing your queries.
According to http://php.net/manual/en/pdo.prepared-statements.php a second advantage is, that statements can be prepared once and executed multiple times.
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. For complex queries this process can take up enough time that it will noticeably slow down an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle. This means that prepared statements use fewer resources and thus run faster.
Nevertheless, if you run your query only once and there is no dynamic data inside your query, omitting prepare is also fine.
In reality, you have to run such a query extremely seldom. A few tables with configuration-like options may be.
In all other cases at least LIMIT clause is obligatory.
So the question is rather a theoretical one.
I've read that if you used mysqli prepare instead of mysqli query it will be run on database only once even if you run the script 1000 times.
does that mean that if i ran a prepare statement like
select * from Table where user=?"
and then mysqli_stmt_bind_param($stmt, "s", "Harry");
and user "harry" doesn't exist in the database so num_rows will return 0.and then i insert immediately a new row in the database with user="harry" and ran the script again, will it return num_rows=1 or still return num_rows=0 because the result is cached?
The fact that you see the newly inserted row depends on other factors... transaction and transaction isolation. Preparing the statement just means that the server knows what is coming and has calculate a plan to optimize the statement. You can then run the query many times, with the same or with different parameters, and the server will not have to analyze it any more... just execute it.
So... to answer your question... the second time you should get num_rows=1. But in case you don't, the problem is not that you prepared a query with parameters... it's something else.
As I now know, mysqli_real_escape_string is not as secure as prepared statements so I'm making the switch.
However I've run across a slight issue with the simplest bit of code.
The query I am expecting to be executed is SELECT * from forums WHERE id=1 and testing this against the database rows are found.
This is the prepared statement code I am using.
$con=mysqli_connect('a','b','c','d');
$forum = $_GET["forum"];
$stmt = mysqli_prepare($con, "SELECT * from forums WHERE id=?");
echo mysqli_stmt_bind_param($stmt, "i", $forum);
mysqli_stmt_execute($stmt);
mysqli_stmt_fetch($stmt);
mysqli_stmt_store_result($stmt);
if (mysqli_stmt_num_rows($stmt)<1){
echo "0";
}
This seems to return 10 which means the query binded successfully but no rows where found.
I'm sorry if this may seem trivial, but this doesn't make much sense to me.
I suppose you also need mysqli_stmt_bind_result, mysqli_stmt_store_result and mysqli_stmt_fetch to get some results out... At least this is what the manual says.
Unless you use mysqli_stmt_store_result, mysqli_stmt_num_rows will return 0 because mysqli hasn't yet fetched the data and doesn't know how many rows there are.
mysqli_stmt_store_result buffers all the resulting data from MySQL in memory for subsequent use by PHP but it can result in out-of-memory errors with large datasets or low memory limits.
Much have been written about the benefits of using PDO::prepare, but little has been written on the benefits of using PDO::query. I believe PDO::query is created to serve a purpose and there ought to be some relative advantage of using this function over PDO::prepare.
I have a query that goes like this:
SELECT * from Table ORDER BY id DESC LIMIT 100;
This query contains no user input for escaping and no variables for repeated querying. Should I use PDO::query, go back to mysqli_query or stick to PDO::prepare in this case?
UPDATE: Further examination on the general query log shows this for both PDO::prepare and PDO::query:
22 Connect user#localhost on Database
22 Prepare SELECT * from Table ORDER BY id DESC LIMIT 100
22 Execute SELECT * from Table ORDER BY id DESC LIMIT 100
22 Close stmt
22 Quit
I was expecting PDO::query to produce:
22 Connect user#localhost on Database
22 Query SELECT * from Table ORDER BY id DESC LIMIT 100
22 Quit
But this only happens, and to both, when setAttribute(PDO::ATTR_EMULATE_PREPARES, true). I am quite surprised at the result that I am getting. It seems that PDO::query generates prepared statements as well.
If you just need it once, then there's no point in creating a prepared statement (which unless emulated would result in two network transmissions to the database). Much less so when there are no variable parameters to be bound.
PDO::query is not about benefits. Its use comes with the absence of any. One-off queries don't benefit from the potential speed advantage of prepared statements.
I guess I have missed it completely. It states in the PHP manual for PDO::query that:
PDOStatement PDO::query ( string $statement )
Parameters
statement
The SQL statement to prepare and execute.
What this means is that the SQL statement is prepared even with PDO::query. Therefore there is absolutely no advantage to use PDO::query except saving a line or two on the PHP script. This is verified by the general query log shown in the question above.