num_rows is working only with `store_result()` - php

num_rows works only if I use mysqli->store_result(). Which means it works only with buffered result. Can someone explain why is this happening?
in the below code when I use mysqli->store_result() then num_rows works. otherwise it says 0.
function retrievearticle($mysqli, $articleid)
{
echo $articleid;
$query="select ArticleText,ArticleTitle from article where ArticleId=?";
$stmt=$mysqli->stmt_init();
$stmt->prepare($query);
$stmt->bind_param('i', $articleid);
$stmt->execute();
$stmt->store_result();
echo "here 2";
$stmt->bind_result($ArticleText, $ArticleTitle);
$stmt->fetch();
echo $stmt->num_rows;
}

As per this comment in the PHP manual, here's an explanation of what you are facing :
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

PHP While loop Update stopping at first row

I made a while loop that will tell if there are items in the transaction history and will put it back in the inventory as the transaction ends but the problem is. It fetches an error called
Uncaught Error: Call to a member function fetch_assoc() on bool in
So I tried the query's one by one and it works.
I tried to experiment and comment the other query and adding a counter++; to tell if the loop works. The problem I found is that after the first if else the counter only add's 1 Where as if I only try this it loops 4 which is right
Query I tried to check the number of loops
$counter=0;
$sql="SELECT * FROM brb_backtransaction WHERE trans_uk='$curr_trans' ";
if($rs=$con->query($sql)){
while ($row=$rs->fetch_assoc()){
$counter++
}
}
It echoes 1234 so it's correct but when the first if else happen it only echo'es 1
$counter =0;
$sql="SELECT * FROM brb_backtransaction WHERE trans_uk='$curr_trans' ";
if($rs=$con->query($sql)){
while ($row=$rs->fetch_assoc()){
$item = $row['trans_item'];
$quan = $row['trans_quantity'];
$sqlsitem="SELECT itmQuantity FROM brb_inventory WHERE itmName='$item'";
if($rs=$con->query($sqlsitem)){
$quanrow = $rs->fetch_assoc();
$currquan = $quanrow['itmQuantity'];
$counter++;
}
I remove other query's as I think this is the problem I ran a total of 3 queries in the while loop.
For your while loop to work it needs access to your original data stream as stored in the $rs variable.
However, further down in your code you are replacing the contents of the $rs variable with a totally new data stream. Therefore, the while loop no longer has access to the original data stream as it is basically throw away.
To solve this, change the second instance to another variable name such as $rs2. That way you have two completely different variables for two different data streams.
With that said, your code is also open to injection attacks. I would recommend looking into PDO and prepared statements.
Also, Tangentially Perpendicular is correct in using SQL JOINS

MySql PDO Prepared Select Statement - Counting Results within Classes via PHP count()

I have quite an issue I can not seem to solve. I am trying to get a row count from a select statement.
I should start by saying I have tried most all methods resulting from google searches on this issue.
I am using the result set so I would prefer not to make a second query.
The query uses a prepared select statement which seems to be a main issue if I understand it correctly.
I decided to try a simple approach using PHP's native count() function. Which lead me here because I finally reached the end of the rope on this.
On to the details...within a class of mine, I make the query like this.
// Create database connection
$database = DatabaseFactory::getFactory()->getConnection();
// Set and execute database query
$sql = "SELECT * FROM `service_orders` WHERE `agency_id` = :agency_id $filter ORDER BY $sort $order $per_page";
$query = $database->prepare($sql);
$query->execute($query_array);
// If results
if ($query->rowCount() > 0) {
$results = $query->fetchAll();
self::$order_count = "Count: " . count($results);
return $results;
}
// Default, return false
return false;
Findings
If I perform count($results) like I did above, I get the total rows in the database (Let's say 50).
If I print_r($results), it shows the array with the proper number of entries (Let's say 10) that of course differs from the total rows in the database.
How can these two differ? It's as if the count($results) is misreading the result array.
More Findings
Within my actual php page, I call the class to retrieve the data like this.
$results = OrderModel::getServiceOrders();
echo count($results);
Strangely enough, if I then perform count($results) it gives me the correct reading of the result array (which in my example here would be 10).
I am perplexed by this as the count function is being performed on the exact same array. The only difference is one is called on the array within the class, and the other is called on the array returned from the class.
Does anyone have any ideas on how to solve this or why there is the discrepancy when using count() in this instance?
Thank you all in advance!
James
Additional Info
This is another mind numbing scenario. If I return the count along with the actual results, I can access it on the page with the correct value (10 rows). Yet, if I set it into a session variable, and access it that way, the count is the whole data set (50 rows). How is it even possible these two values are not the same?!
$results = $query->fetchAll();
Session::set("order_count", $total[0]); // Yields 50 (incorrect)
return [
"results"=> $results,
"count"=> $total[0], // Yields 10 (correct)
];

check if PDO query returns results

Assume I have this piece of code:
foreach($creds as $cred){
$prev_fut = $pdo->query("SELECT importo FROM incassi_prev WHERE
data_prev='$data_fut' AND incasso=0 AND
id_cre='{$cred['id_cre']}'")->fetch();
if(count($prev_fut)>0){
//I have found a result
}else{
//I have found nothing
}
}
NOTE: It is an internal query for my application with no data posted by user so I don't worry about SQL injections.
I use to check if count($prev_fut)>0 to see if the query is returning data (if I find any row in the db with these criterias).
My question is:
is this check enough to verify that the query has at least a result? Is it better to perform any other check?
The question is mostly coming from my thoughts about this being in a for loop and is related to the option of emptying/unset the $prev_fut array before starting a new iteration of for loop.
fetchColumn returns a single value of the next row in the result set. count counts the length of an array. Since fetchColumn can't return an array (for most database implementations), using count on it is wrong. You want to test whether $prev_fut is false or not. false would indicate that no result could be fetched, while anything else means a result was fetched:
if ($prev_fut !== false) ..
Having said that, you should really use a COUNT() in the database and check that value:
$result = $pdo->query('SELECT COUNT(*) FROM ...')->fetchColumn();
if ($result > 0) ..
It's much more efficient to have the database count and summarise the result than fetching an entire result set into PHP just for this simple check.

How to get the type of a query statement in PDO?

In the MySQL Reference Manual, there's distinction between data definition statements and data manipulation statements.
Now I want to know if a query inserts a database record, updates one, deletes one or modifies the table structure and so on, or, more precisely, the exact number of affected rows, but only if it is applicable.
For example, the statement
SELECT *
FROM SomeTable
WHERE id=1 OR id=2
returns a number of affected rows (in this case 2), but with the SELECT statement, there's nothing modified in the database, so that number would be 0.
How to get the type of query?
I was looking for the same answer and stumbled across this article. It was last updated in August. In it, there is a section: "Determining the Type of a Statement" You basically can make the following assumptions: (copied from the article)
If columnCount() is zero, the statement did not produce a result set. Instead, it modified rows and you can invoke rowCount() to determine the number of affected rows.
If columnCount() is greater than zero, the statement produced a result set and you can fetch the rows. To determine how many rows there are, count them as you fetch them.
I'll save you the trouble and just paste the code sample here
$sth = $dbh->prepare ($stmt);
$sth->execute ();
if ($sth->columnCount () == 0)
{
# there is no result set, so the statement modifies rows
printf ("Number of rows affected: %d\n", $sth->rowCount ());
}
else
{
# there is a result set
printf ("Number of columns in result set: %d\n", $sth->columnCount ());
$count = 0;
while ($row = $sth->fetch (PDO::FETCH_NUM))
{
# display column values separated by commas
print (join (", ", $row) . "\n");
$count++;
}
}
I have been thinking of the same issue, and come to conclusion that I don't need no automation in this matter.
The only use for such an auto-detect is some magic function which will return number of affected rows. But such a magic, although adding a little sugar to the syntax, always makes code support a nightmare:
When you're calling a function, and it can return values of different types depends on the context, you cannot tell which one is returned at every particular moment. So, it makes debugging harder.
So, for sake of readability, just call appropriate function to get the result you need at the moment - affectedRows or numRows. It won't make your code bloated, but make it a lot readable.
I'm using this:
substr($statement->queryString, 0, strpos($statement->queryString, ' '));
where $statement is a PDOStatement object, a few things to note here are that you should verify before using this that $statement is a PDOStatement object, also we should probably take the strpos out of the substr statement in case strpos returns false, which would probably cause an error, finally, this only works with one word statement types, like SELECT, INSERT, etc and not multi-word statement types like ALTER TABLE

Is it possible to check if pdostatement::fetch() has results without iterating through a row?

I have a page which needs to check for results, and the way I came up with to do it is successful, but iterates through the first row of results. Is there a way I can check without iterating, or to go back to that first row without executing the query again?
I was doing this:
$q = pdo::prepare($SQL);
$q->execute(array(':foo'=> foo, 'bar'=>bar);
if(!q->fetch){
//no results;
}else{
//results;
};
It does pretty much exactly what I hoped, with the unfortunate side affect of skipping the first row of results.
I've resorted to running $q->execute() a second time. Is there a way to avoid doing this?
Just put the result of fetch into a variable:
if($row = $q->fetch()) {
// $row contains first fetched row
echo $row['coloumn_name'];
}
else
// no results
If you want to be lazy, you could always do something like:
$totalRows = count($resultSet->fetchAll());
However, this is less than efficient for large result sets.
Otherwise, see the manual page about rowCount() (particularly example #2) for what appears to be the standard workaround. There are some interesting user-supplied comments on that page as well.
May be you'll find SELECT FOUND_ROWS() usefull for this. See example at php.net site http://www.php.net/manual/en/ref.pdo-mysql.php#77984
rowCount() is known to work with mysql, so if portability is not a concern, use that.
otherwise, you can try to change the program logic, e.g.
$stmt->execute();
$count = 0;
foreach($stmt as $record) {
// output...
$count++;
}
if(!$count)
echo "no results!";

Categories