What is the difference between mysqli_affected_rows and mysqli_num_rows? - php

The PHP docs for mysqli_num_rows says
Returns the number of rows in the result set.
The PHP docs for mysqli_affected_rows says
Returns the number of rows affected by the last INSERT, UPDATE, REPLACE or DELETE query.
_num_rows is called on a result, and _affected_rows is called on a connection. Since I think they do the same thing(correct this assumption if I'm wrong), I'm wondering whether one works better than the other, and which situations would call for which function.
Aren't number of rows affected and number of rows in the result set synonymous?

num_rows tells you how many rows there are in the result set you just selected with a SELECT query. affected_rows tells you how many rows where affected by an INSERT, UPDATE, REPLACE or DELETE query. The difference is obvious:
$resultSet = mysqli_query($c, 'SELECT ...');
echo mysqli_num_rows($resultSet);
SELECT result set goes into num_rows.
mysqli_query($c, 'UPDATE ...');
echo mysqli_affected_rows($c);
No result set, no num_rows.

mysql_affect_rows counts on how many rows your UPDATE/INSERT query was used
and mysql_num_rows counts how many rows your SELECT statement found

I'd like to add, in recent versions of mysql this may have changed.
I was recently looking for the difference and found that while yes mysqli_num_rows counts how many rows your SELECT statement found.
mysqli_affected_rows will count how many rows your UPDATE/INSERT/DELETE/REPLACE and SELECT statement 'affected'.
Unless you are trying to compare between the number of rows returned in a SELECT statement vs. the number of rows affected in an UPDATE/INSERT/DELETE/REPLACE than there is no huge concern over which you need to be using. If you want to be semantically correct than use the appropriate one for the corresponding statement.
https://dev.mysql.com/doc/refman/8.0/en/mysql-affected-rows.html
For SELECT statements, mysql_affected_rows()
works like mysql_num_rows()

Related

Is there a real difference between mysqli::num_rows and mysqli::affected_rows when doing a SELECT

I have been looking for a definate answer on this, but opinions on the internet slightly vary.
I am used to differentiating between using mysqli::num_rows and mysqli:affected_rows for the intended purposes. However, I read in the PHP manual that affected_rows will behave like num_rows when a select query has been executed.
My actual question is this: Is there any downside to ALWAYS using affected_rows and forgetting about num_rows? If affected_rows behaves like num_rows, what use is num_rows? Using only affected_rows would simplify my DB library code in PHP.
There are two types of operations related table records (Not table structure):
1) Select: When you are only fetch the data from table.
2) Update: When you updating the table records (Insert/Update/Delete) all these operations will update/change your table records.
If you run the select query the num_rows will work because it returns a count of rows. But when you run Insert/Update/Delete query affected_rows will work because it returns how many rows affected by your Insert/Update/Delete query.
Also, Mysql server returns affected rows when you run Insert/Update/Delete query. PHP function affected_rows convert this response directly with connection resource/object. But when you run select query mysql server returns result-set. And by using this result php function num_rows returns that result set has how many rows. For affected_rows we are using connection resource/object and for num_rows we are using result resource/object.

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.

Why don't PHP's MySQL libraries associate affected_rows with the query result object?

This is a pretty straightforward question I think, but I'll explain my thinking:
Unless I'm mistaken, the number of affected rows is always inherently linked to a query that has been performed. Similarly, the number of rows returned by a SELECT are inherently linked to that query, and the value is retrieved as such:
echo $mysql_result_object->num_rows;
Why is it that to retrieve the affected rows from something like an UPDATE or DELETE statement, one should access the value through the connection object?
echo $mysql_connection_object->affected_rows;
It doesn't seem very logical to me.
Is it simply because query functions (for example mysqli_query) return boolean true for INSERT/UPDATE/DELETE statements? In which case... shouldn't they return an empty result object?
You pretty much answered your own questions, so I'm just clarifying really.
num_rows operates on the result set. It is therefore only valid for operations that return a result set. i.e. SELECT or SHOW.
INSERT, UPDATE and DELETE do not return a result set. To answer your last sentence; they cannot return an empty result set, since they are already returning a boolean.
affected_rows will return the number of affected rows for the last query associated with a link_identifier.
So, you cannot use num_rows for INSERT, UPDATE, DELETE, but you can use affected_rows for for a SELECT, in which case it operates like num_rows.

Get Number of Rows from a Select Statement Efficiently

Until recently I've been using mysql_real_escape_string() to fix most of my variables before making SQL queries to my database. A friend said that I should be using PDO's prepared statements instead, so after reading a bit about them I'm now switching over to them.
I've only encountered one problem so far in switching over, and that's counting the rows to returned by a SELECT statement. On occasion in my code, I'd run an SQL query and then count the number of rows returned from the SELECT statement. Depending on whether a result set returned, I would take different actions. Sometimes I do need to use the result set from it. MySQL let me go straight to mysql_fetch_assoc() after mysql_num_rows() with no problem. However, PDO doesn't seem to have anything like mysql_num_rows().
I've been reading some responses on SO that gave me a solution, to either use COUNT() in the SQL statement or to use the PHP function count() on the result set. COUNT() would work fine in the SQL statement if I didn't need the result set in some places, however, several people have mentioned that using count() on the result set is fairly inefficient.
So my question is, how should I be doing this if I need to count the number of rows selected (if any), then run a script with the result set? Is using count() on the result set the only way in this case, or is there a more efficient way to do things?
Below is a short example of something similar to my previous SQL code:
$query=mysql_query('SELECT ID FROM Table WHERE Name='Paul' LIMIT 1);
if(mysql_num_rows($query)>0)
{
print_r(mysql_fetch_assoc($query));
}
else
{
//Other code.
}
Thanks.
EDIT
I do know that you use fetchAll() on the statement before counting the result set (which gives me what I need), but I'm just trying to figure out the most efficient way to do things.
$stmt->rowCount();
http://php.net/manual/en/pdostatement.rowcount.php
the rows must be fetched(buffered into memory, or iterated) for it to work. It's not uncommon for your pdo driver to be configured to do this automatically.
You will have to use Count(). You can run two queries like
SELECT COUNT(ID) FROM Table WHERE Name='Paul'
one you have get the count, then run the query with select clause
SELECT ID FROM Table WHERE Name='Paul' LIMIT 1
Count() function is not inefficient at all if you are using it like COUNT(ID), because most probably id is primary key and have an index. MYSQL wont even have to access the table.

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