Get Number of Rows from a Select statement - php

I have this:
$dbh = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=$mdbFilename", $username, $password);
$sql = "SELECT * FROM this_table";
$stmt = $dbh->query($sql);
//num of rows?
How do I get the number of rows returned from that SELECT statement?
Thanks all

SELECT count(*) FROM this_table is an option...
Regarding rowCount:
PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. **
However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.

I have found a solution, using fetchAll and then using count on this array - which is what MySQL does anyway internally, a bit inefficient but it works for me.
$q = $db->query("SELECT ...");
$rows = $q->fetchAll();
$rowCount = count($rows);
From another question Chad provided this insight:
It seems as though the only reason
this was possible with MySQL is
because it internally fetched all the
result rows and buffered them, to be
able to give you this information. See
mysql_unbuffered_query(). If you use
that function instead of
mysql_query(), the mysql_num_rows()
function will not work. If you really
need to know the number of rows while
using PDO, you can fetch all of the
rows from PDO into an array and then
use count().
Hope this is useful to someone.

Related

Is there a way to use SELECT FOUND_ROWS() in php and mysqli?

I'm trying to implement a pagination system into my website and can't get past this one stubborn error. I'm not exactly sure if you can use FOUND_ROWS() in mysqli as opposed to PDO but that's what I came here for.
I have the latest version of PHP and everything worked up to this point in the pagination.
$stmt = $conn->prepare('SELECT count(*) FROM owned_assets WHERE uid=? AND type=? LIMIT '.$start.', '.$rLim);
$stmt->bind_param('ii', $uid, $assetType);
$stmt->execute();
$total = $conn->query('SELECT FOUND_ROWS() as total')->mysqli_fetch_array()['total'];
What's supposed to happen (so far) is mysql will count the rows found within the matching query and I can work further on from there.
This is my current error:
Fatal error: Uncaught Error: Call to a member function mysqli_fetch_array() on bool
Of course there is but you have to follow the proper routine.
Your current query makes no sense as it counts the number you already know, stored in $rLim (all right not always but that's not the point).
To use FOUND_ROWS() for pagination you must add SQL_CALC_FOUND_ROWS to your query that fetches the data for a single page.
Then you will be able to get the total number of rows without limit by means of running another query with FOUND_ROWS().
That said, using SQL_CALC_FOUND_ROWS is not recommended as it is as slow as fetching all rows without LIMIT. And this is the reason why this function was recently deprecated.
So you have to make two queries, one fetching the actual data with LIMIT clause and one with count(*) and without LIMIT.
You already have the counting query, just fetch that value. No need for another second query FOUND_ROWS().
$stmt = $conn->prepare('SELECT count(*) FROM owned_assets WHERE uid=? AND type=?');
$stmt->bind_param('ii', $uid, $assetType);
$stmt->execute();
$result = $stmt->get_result();
$total = $result->fetch_assoc();
echo $total['count(*)'];
Sidenote: You can use an alias to count(*) AS total in the query, and access the index as $total['total'] in the return value.
You don't need another query to get the total number of rows, as you already have it with COUNT(). You can just bind the result of the first query to the $total with bind_result():
$stmt->bind_result($total);

Using Prepared PDO statements

I'm running queries using the PDO prepared statement, MySQL db. When I run a query, I haven't found a way to know the number of affected rows if any, I've tried rowCount() but still to no avail.
$stmt1 = $db->prepare("SELECT * FROM publications WHERE pub_journal = '$j' AND pub_issue = 'CURRENT'");
$stmt1->execute();
How can I find the number of affected rows?
rowCount should work if your database is MySQL. The fact that it hasn't worked for you indicates that your query may be failing, or that it does not return the number of rows you expect it to.
The PDO documentation suggests the following approach to find the number of rows:
For most databases, PDOStatement::rowCount() does not return the number of rows affected by a SELECT statement. Instead, use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement, then use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned.
This should work with a prepared statement as well as with PDO::query().
You can modify your original SQL to be used as a template, so that it can take either COUNT(*) or * (or even better, a list of the specific columns you need).
$sql = "SELECT %s FROM publications WHERE pub_journal = ? AND pub_issue = 'CURRENT'";
Notice the ? in the SQL. This is a placeholder to which the $j variable will be bound when the statement is executed with execute([$j]);. When you concatenate your variables into the SQL string (like ...WHERE pub_journal = '$j'...) you really aren't getting much of the benefit of prepared statements.
With this, you can prepare and execute your count query:
$count_stmt = $db->prepare(sprintf($sql, 'COUNT(*)'));
$count_stmt->execute([$j]);
Then get the count with:
$count = $count_stmt->fetchColumn();
After you do whatever you need to do with the count, you can execute the actual SELECT query by specifying which columns you want rather than COUNT(*).
$select_stmt = $db->prepare(sprintf($sql, '*'));
$select_stmt->execute([$j]);
rowcount() should only be used for DELETE, INSERT, or UPDATE statements, though it may work for SELECTs in some cases. What you can do is this, though:
$res = $stmt->fetchAll();
$count = count($res);
And $count will hold the number of rows.

PHP PDO How does rowCount() get it's results?

Does PHP's PDO run a silent select count(*) statement for it's rowCount() when used after a select statement, or does it get it's result using some other approach?
$query = $conn->prepare('select name, alias from accounts where status = 0');
$query->execute();
$queryCount = $query->rowCount();
$profiles = $query->fetchAll(PDO::FETCH_ASSOC);
if($queryCount > 0) {
print_r($profiles);
} else {
echo 'No records found';
}
In the above code, everything runs fine, and I'm able to get the correct number of rows as the result. But is there a count statement running in there? How does PHP do this?
That depends on the PDO database driver really. Despite what the manual says, it usually works for MySQL connections. With recent versions of mysqlnd anyway. Older versions and the old libmysqlclient interface can be initialized with PDO::MYSQL_ATTR_FOUND_ROWS to also return row counts for SELECT statements.
There's no automatic SELECT COUNT() requery when you ask for ->rowCount(). The driver receives and keeps a uint64_t row_count; internally. Server responses pretty much always include a result row count for prepared statements.
For ->fetchAll and iterations, the PDO mysqlnd driver even just manually set->row_count++ calculates it.
Have a look at https://github.com/php/php-src/blob/master/ext/mysqlnd/mysqlnd_result.c for what's actually happening.
The older mysql driver calls mysql_num_rows.c which only returns the correct result count after all rows have been fetched.
From here:
Example #2 Counting rows returned by a SELECT statement
For most databases, PDOStatement::rowCount() does not return the
number of rows affected by a SELECT statement.
Means: you may not rely on what you have currently implemented!
No. From the docs:
For most databases, PDOStatement::rowCount() does not return the number of rows affected by a SELECT statement. Instead, use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement, then use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned. Your application can then perform the correct action.
In the deprecated PHP function mysql_num_rows(), the MySQL function mysql_num_rows() was used. I suppose PDO does the same.
More information can be found here.
NB: this means that your current code may work in some cases, but you can't rely on it. Use a COUNT(*) query instead.
From PHP's docs:
PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.

How to combine two PDO statements in one MySQL query?

From what I know now about PDO statements and my own experiences on localhost and Google - there are some difficulties with using multiple PDO statements in one query. For instance this situation:
$stmt = $db_people->prepare("SELECT * FROM people WHERE online=1");
$stmt->execute();
$results_people = $stmt->fetch(PDO::FETCH_ASSOC);
On this query I can do simple PDO statement like fetch (in example). But when I want to use PDO statement like this:
$rows = $stmt->rowCount();
It is not possible and the statement will not return the right number of rows. When I do it in the other way around and filling one of the column name - rowCount works correctly like this:
$stmt = $db_people->prepare("SELECT name FROM people WHERE online=1");
$stmt->execute();
$rows = $stmt->rowCount();
And adding fetch after that like this:
$results_people = $stmt->fetch(PDO::FETCH_ASSOC);
Will not work corectly in this example. My question is - How to combine two different PDO statements in one single query? Thank you.
The answer probably depends on which operations you're trying to combine. For instance, if you're trying to combine PDOStatement::rowCount() with a SELECT SQL operation, then it's probably worthwhile to take notice of the warnings in the PDOStatement::rowCount() description which says that rowCount() is not 100% reliable for SELECT statements in all databases.
If the problem you're trying to solve is specifically limited to counting the result rows of a SELECT, then another approach would be to use PDOStatement::fetchAll() and count the rows in the returned array.

Work-around for PHP5's PDO rowCount MySQL issue

I've recently started work on a new project using PHP5 and want to use their PDO classes for it. The problem is that the MySQL PDO Driver doesn't support rowCount() so there's no way to run a query and then get the number of affected rows, or rows returned, which is a pretty big issue as far as I'm concerned. I was wondering if anyone else has dealt with this before and what you've done to work around it. Having to do a fetch() or fetchAll() to check if any rows were affected or returned seems like a hack to me, I'd rather just do $stmt->numRows() or something similar.
You can issue a SELECT FOUND_ROWS() query right after the original SELECT query to get row count.
$pdo->query("SELECT * FROM users");
$foundRows = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
See also: MySQL Docs on FOUND_ROWS()
For those of you who are using MySQL stored procedures, this solution isn't really feasible. What I would suggest that you do is have your stored procedure create two rowsets. The first one will contain one row and one column, containing the number of records. The second will be the recordset you will use for fetching that number of rows.
The number of unlimited rows can be a SELECT COUNT(*) with the exact same WHERE clause as the second rowset without the LIMIT/OFFSET clauses.
Another idea could be to create a temporary table. Use your SELECT statement to populate the temporary table. Then you can use SELECT COUNT(*) FROM tmpTable for your first rowset and SELECT * FROM tmpTable for your second.
This question is based on several false assumptions and one outdated statement.
First of all, do not confuse number of affected and selected rows. PDO supported the former even back in '09.
Speaking of number of rows returned by SELECT statement - you just don't need that number. The data you have is enough.
And yeah, nowadays rowCount() supports number of rows selected from mysql as well. But again - you don't need that number in an average web-application anyway.

Categories