$result->num_rows always returns 0 [duplicate] - php

This question already has an answer here:
Why does mysqli num_rows always return 0?
(1 answer)
Closed 1 year ago.
after reading tons of threads, tutorials and whatever - I feel like posting here and hope that someone can help me.
I tried out every advice I could get, but it's still not working.
Here is my code :
$prep_stmt = "SELECT id, DATE_FORMAT(added,'%d.%M'), title FROM offers ORDER BY added DESC LIMIT ?, ?;";
$stmt = $mysqli->prepare($prep_stmt);
$stmt->bind_param ('ii',$lowlimit, $page);
$stmt->execute();
$stmt->bind_result($id, $added, $title);
while ($stmt->fetch()) {
... # some random output here
}
$count = $stmt->num_rows;
echo "c -> ". $count;exit;
I always get "c -> 0" ... but there IS output already ... so what am I doing wrong ? :/

You need to call the store_result() method before accessing the num_rows property.
From a comment on PHP manual documentation:
If you do not use mysqli_stmt_store_result(), and immediately call this function after executing a prepared statement, this function will usually return 0 as it has no way to know how many rows are in the result set as the result set is not saved in memory yet.
mysqli_stmt_store_result() saves the result set in memory thus you can immedietly use this function after you both execute the statement AND save the result set.
Your code should look like:
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($id, $added, $title);
while ($stmt->fetch()) {
# some random output here...
}
$count = $stmt->num_rows;

Taken from php.net You have to store it first.
$stmt->store_result();
$count = $stmt->num_rows

From the PHP manual, first comment http://fr2.php.net/manual/fr/mysqli-stmt.num-rows.php :
Please be advised, for people who sometimes miss to read this important Manual entry for this function:
If you do not use mysqli_stmt_store_result( ), and immediatley call
this function after executing a prepared statement, this function will
usually return 0 as it has no way to know how many rows are in the
result set as the result set is not saved in memory yet.
mysqli_stmt_store_result( ) saves the result set in memory thus you
can immedietly use this function after you both execute the statement
AND save the result set.
If you do not save the result set but still want to use this function
you have to actually loop through the result set one row at a time
using mysqli_stmt_fetch( ) before using this function to determine the
number of rows.
A thought though, if you want to determine the number of rows without
storing the result set and after looping through it, why not just
simply keep an internal counter in your loop every time a row is
fetched and save the function call.
In short, this function is only really useful if you save the result
set and want to determine the number of rows before looping through
it, otherwise you can pretty much recreate its use like I suggested.

Related

What is the difference between get_result() and store_result() in php?

This is my code. I am checking if a user exists or not in a login/registration system:
public function userExist($email){
$stmt = $this->conn->prepare("select email from users where email= ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows>0){
}
else{
}
}
Can I use get_result instead of store_result() ?
It depends on how you plan to read the result set. But in the actual example you have given, you are not interested in reading any returned data. The only thing that interests you is whether there is a record or not.
In that case your code is fine, but it would work equally well with get_result.
The difference becomes more apparent, when you want to get for example the userid of the user with the given email:
SELECT id FROM users WHERE email = ?
If you plan to read out that id with $stmt->fetch, then you would stick to
store_result, and would use bind_result to define in which variable you want to get this id, like this:
$stmt->store_result();
$stmt->bind_result($userid); // number of arguments must match columns in SELECT
if($stmt->num_rows > 0) {
while ($stmt->fetch()) {
echo $userid;
}
}
If you prefer to get a result object on which you can call fetch_assoc() or any of the fetch_* variant methods, then you need to use get_result, like this:
$result = $stmt->get_result(); // You get a result object now
if($result->num_rows > 0) { // Note: change to $result->...!
while ($data = $result->fetch_assoc()) {
echo $data['id'];
}
}
Note that you get a result object from get_result, which is not the case with store_result. You should get num_rows from that result object now.
Both ways work, and it is really a matter of personal preference.
As usual, the accepted answer is too localized, being much more focused on the insignificant details than on the answer itself.
There is also, sadly, a deleted answer, which, although being laconic, makes a perfect rule of thumb:
Use get_result whenever possible and store_result elsewhere.
Both functions load the pending resultset from the database to PHP process' memory, with get_result() being much more versatile and therefore preferred.
The only difference between get_result() and store_result() is that the former gets you a familiar mysqli_result resource/object which can be used to fetch the data using familiar fetch_row() / fetch_assoc() routines, as well as a slightly modern fetch_all(), all of those being incomparably more convenient than bind_result() routine which is the only option with store_result().
It could be noted that get_result() is only available when mysqlnd driver is used, which is not an issue in 2019 and beyond. If it's not available, you are probably to tick some checkbox in your shared host's configuration.

MYSQLi store result and then get result

I have a function which does the following things
$stmt = mysqli_prepare..
//check for preparation failure
mysqli_stmt_bind_param
//Check for bind error
mysqli_stmt_execute
//Check for execution error
mysqli_stmt_store_result //Problem is here
//Check for error
return $stmt
I have these steps in a function because I need it in two placeds the same piece of code. After getting the stmt, I need to check number of rows [mysqli_Stmt_num_rows]. So only I have that stored result stmt at the end of the function.
After checking the rows, i need to get a column value from the result. So I tried to execute mysqli_stmt_get_result on the returned statement object. It fails.
I just removed the store result part and just returned the executed stmt from the function. Get result works then. But I cannot count rows until I store the result.
Then I have done simple trick that tried to clone the returned statement. Unfortunately, mysqli stmt is not clonable.
How do I solve this issue?
mysqli_result class also has a property called num_rows
$result = $stmt->get_result();
echo $result->num_rows;
If you want to stick to procedural style, which I do not recommend, there is a corresponding function mysqli_num_rows($result)

PHP MySQLi prepared statement fetch - first row empty?

The following code:
$con = ConnectDB::getConnection();
if ($stmt = $con->prepare('---SQL here with 1 param---')) {
$stmt->bind_param('i', $this->id);
$stmt->execute();
$stmt->bind_result($device_id, $device_identifier);
while ($stmt->fetch()) {
$device = new Device($device_identifier, $device_id);
$all_devices[] = $device;
}
fetches an empty result? The first time through the loop, the $device_id and $device_identifier is empty, but the fetch() method returns true so it runs. HOWEVER - the SECOND iteration actually contains my result.
I could simply check if they are empty and ignore them, but i really can't understand why it is returning an empty pair? I tried running the SQL directly on the DB and it just returns 1 result row?
Any ideas?
As you may imagine, MySQLi prepared statement fetch does not return an empty first row. As such a behavior would make a very little sense.
You need to learn to create a correct proof for your assertions.
The code you posted is incorrect one. For some reason you are trying to judge a matter by indirect consequences. Why not to examine the matter itself?
$con = ConnectDB::getConnection();
if ($stmt = $con->prepare('---SQL here with 1 param---')) {
$stmt->bind_param('i', $this->id);
$stmt->execute();
$stmt->bind_result($device_id, $device_identifier);
$stmt->fetch();
var_dump($device_identifier, $device_id);
-- this code will tell you unambiguously, if your assumption on empty result was right or wrong.
After learning that, you may start debugging, to find a spot in your own code that is responsible for the current behavior.
Hope it helps.

mysqli prepared statement , how to loop the result set

I was researching about mysqli prepared statements and i have 2 questions about it.
As i was reading, i figure out that the order of execution of a prepared statement looks something like the following:
$sql = 'SELECT image_id, filename, caption FROM images WHERE image_id = ?';
// connect to the database
$conn = ....
$stmt = $conn->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($image_id, $filename, $caption);
// optional: get total of records in the result set
$stmt->store_result();
$numRows = $stmt->num_rows;
// loop through the result set
while ($stmt->fetch()) {
// code goes here...
}
or
// fetch the result for one record
$stmt->fetch()
// free & close
$stmt->free_result();
$stmt->close;
$conn->close();
Here's my first question:
As i was reading, it also mentions the following:
If you don't bind the result to variables, use $row = $stmt->fetch(), and access each variable as $row['column_name']. So,
Are they any pros/cons using either of the 2 methods to loop the result set?
If there's no difference, then why bother binding the result using $stmt->bind_result in the first place? What's the point if i can use $row = $stmt->fetch() instead?
Here's my other question:
$stmt->free_result(); frees what exactly? the prepare() or the store_result() or else ?
$stmt->close; what am i closing exactly? the stmt_init() or the prepare() or else?
Hopefully your answers will make me understand better prepared statements so i can build something safe...
Thanks
$stmt->free_result() does pretty much what the name says: it frees the memory associated with a result.
$stmt->close closes the statement handle (the cursor actually), making it impossible to loop through the result set (again).
Although the manual states: 'You should always free your result with mysqli_free_result(), when your result object is not needed anymore', common practice is not to use free_result and close on a statement. When closed you cannot use the result set anymore, or reuse it and when php dies, memory is freed anyway.

PDO “Uncaught exception 'PDOException' .. Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll().”

I know this question has been asked many times, but I've read the answers to many of the questions and still cannot understand why I am receiving this error:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while
other unbuffered queries are active. Consider using
PDOStatement::fetchAll(). Alternatively, if your code is only ever
going to run against mysql, you may enable query buffering by setting
the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.'
The first thing that is odd, is that I do not get an error on my localhost (wampserver), but I do get it on my web server. The php version on my localhost is 5.3.10, and on my web server it is 5.3.13.
I have read that the source of this error is making a query when data left in the buffer from a previous query. This is not the case for me -- I have echo'd out all of the data and I know for a fact that every row returned in a query is being fetched.
With that said, I have found that changing one of my queries to fetchAll instead of fetch fixes the problem, but it simply makes no since because I know that all of the rows returned are being read. When I used fetchAll for the query (it is being made in a loop), I printed out the array each loop, and only one item was in the array for each query in the loop.
One more piece of information. It's not the query that I changed to fetchAll (which makes the error go away) that throws the PDO error, there is another query later in my php file that throws the error. My file is basically like this:
... code ...
query 1
... code ...
loop
query 2
end loop
... code ...
query 3
If I comment out query 3, there is no error. If I comment out, or change to fetchAll, query 2, there is no error. query 1 has no affect whatsoever.
I would also like to add that I have tried adding LIMIT 1 to all of the queries on the page (at the same time), and the error is still there. I think this proves there is not unread data in the buffer, right?
I'm really confused, so I would appreciate your advice. Before someone asks, I can't post the full code for this, but here is a simplified version of my code:
$stmt = $this->db->prepare('SELECT ... :par LIMIT 1');
makeQuery($stmt, array(':par' => $var));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt = $this->db->prepare('SELECT ... :par LIMIT 1');
for loop
makeQuery($stmt, array(':par' => $var));
$row2 = $stmt->fetch(PDO::FETCH_ASSOC);
... [use row2] ...
end for loop
$stmt = $this->db->prepare('SELECT ... :par LIMIT 1');
makeQuery($stmt, array(':par' => $var));
$row3 = $stmt->fetch(PDO::FETCH_ASSOC);
Here is makeQuery().
/**************************************************************************************************************
* Function: makeQuery *
* Desc: Makes a PDO query. *
* Pre conditions: The statement/query and an array of named parameters (may be empty) must be passed. *
* Post conditions: The PDO query is executed. Exceptions are caught, displayed, and page execution stopped. *
**************************************************************************************************************/
function makeQuery($stmt, $array, $errMsg = '')
{
try
{
$stmt->execute($array);
}
catch (PDOException $e)
{
print $errMsg != ''?$errMsg:"Error!: " . $e->getMessage() . "<br/>";
die();
}
}
Thanks for your help!
EDIT: I also tried doing the following after query 2 (since that seems to be the source of the problem:
$row2 = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($row2);
The output was:
bool(false)
Have I stumbled across a PDO bug?
You need to fetch until a row fetch attempt fails. I know you may only have one row in the result set and think one fetch is enough, but its not (when you're using unbuffered queries). PDO doesn't know how many rows there are until it reaches the end, where it tries to fetch the next row, but it fails.
You probably have other statements where you didn't fully "fetch until a fetch failed". Yes, I see that you fetch until the fetch failed for one of the statements, but that doesn't mean you did it for all of them.
To clarify -
When you execute a query via execute(), you create a result set that must be fetched from the db into php. PDO can only handle 1 of these "result set in progress of being fetched" at a time (per connection). You need to completely fetch the result set, all the way to the end of it, before you can start fetching a different result set from a different call to execute().
When you "call fetch() until a fetch() fails", the fact that you reached the end of the results is internally noted by PDO when that final call to fetch() fails due to there being no more results. PDO is then satisfied that the results are fully fetched, and it can clean up whatever internal resources between php and the db that were established for that result set, allowing you to make/fetch other queries.
There's other ways to make PDO "call fetch() until a fetch() fails".
Just use fetchAll(), which simply fetches all rows, and so it will hit the end of the result set.
or just call closeCursor()
*if you look at the source for closeCursor(), the default implementation literally just fetches the rows and discards them until it reaches the end. It's written in c obviously, but it more or less does this:
function closeCursor() {
while ($row = $stmt->fetch()) {}
$this->stmtFullyFetched = true;
}
Some db drivers may have a more efficient implementation that doesn't require them to fetch lots of rows that nobody cares about, but that's the default way PDO does it. Anyway...
Normally you don't have these problems when you use buffered queries. The reason is because with buffered queries, right after you execute them, PDO will automatically fully fetch the db results into php memory, so it does the "call fetch() until a fetch() fails" part for you, automatically. When you later call fetch() or fetchAll() yourself, it's fetching results from php memory, not from the db. So basically, the result set is immediately fully fetched when using buffered queries, so there's no opportunity to have more than 1 "result set in progress of being fetched" at the same time (because php is single threaded, so no chance of 2 queries running at the same time).
Given this:
$sql = "select * from test.a limit 1";
$stmt = $dbh->prepare($sql);
$stmt->execute(array());
Ways to fully fetch the result set (assuming you only want the first row):
$row = $stmt->fetch();
$stmt->closeCursor();
or
list($row) = $stmt->fetchAll(); //tricky
or
$row = $stmt->fetch();
while ($stmt->fetch()) {}
After struggling with this issue for days, I finally found that this worked for me:
$db = new PDO ($cnstring, $user, $pwd);
$db->setAttribute (PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
This also happen if you are trying to fetch a non SELECT query (Eg - UPDATE/INSERT/ALTER/CREATE). Make sure to use fetch or fetchAll only for SELECT queries.
Possible Duplicate Answer/Question

Categories