The MySQL Connector/Python cursor rowcount property reports the number of rows returned by a SELECT statement or affected by data-changing statements such as INSERT, UPDATE and DELETE.
count=my_cursor.rowcount
execute(), so rowcount is immediately available. With a non-buffered cursor, rowcount starts at -1 and increases as rows are fetched.First create a MySQL connection using mysql.connector.
import mysql.connector
my_connect=mysql.connector.connect(
host='localhost',
user='userid',
password='password',
database='database_name'
)
my_cursor=my_connect.cursor()
The cursor executes SQL statements and provides properties such as rowcount.
A buffered cursor fetches all rows returned by the server after the statement is executed.
my_cursor=my_connect.cursor(buffered=True)
sql='SELECT * FROM student WHERE class=%s'
my_cursor.execute(sql, ('Five',))
print('Rows returned =', my_cursor.rowcount)
Sample Output
Rows returned = 11
The actual number depends on the data in the table.
Because the complete result has already been buffered, rowcount contains the total number of selected rows immediately after execute().
rows=my_cursor.fetchall()
for row in rows:
print(row)
The default cursor is normally non-buffered.
my_cursor=my_connect.cursor()
my_cursor.execute(
'SELECT * FROM student WHERE class=%s',
('Five',)
)
print(my_cursor.rowcount)
Immediately after execution, the output is:
-1
This does not mean that the query returned no rows. It means the non-buffered cursor has not yet fetched enough rows to know the complete result count.
With a non-buffered cursor, rowcount changes as records are retrieved.
my_cursor=my_connect.cursor()
my_cursor.execute('SELECT * FROM student WHERE class=%s', ('Five',))
print('Before fetching:', my_cursor.rowcount)
row=my_cursor.fetchone()
print('After fetchone():', my_cursor.rowcount)
remaining=my_cursor.fetchall()
print('After fetchall():', my_cursor.rowcount)
If 11 rows match, a typical result is:
Before fetching: -1
After fetchone(): 1
After fetchall(): 11
The cursor starts with an unknown row count and updates it as rows are fetched.
for row in my_cursor:
print(row)
print('Rows fetched =', my_cursor.rowcount)
After all returned rows are consumed, rowcount reflects how many records were fetched.
If the application only needs to know how many database rows match a condition, use SQL COUNT(*) instead of fetching every record.
sql='SELECT COUNT(*) FROM student WHERE class=%s'
my_cursor.execute(sql, ('Five',))
count=my_cursor.fetchone()[0]
print('Students in class Five =', count)
Sample Output
Students in class Five = 11
| Requirement | Recommended Approach |
|---|---|
| Need the actual rows | SELECT ... and fetch the result |
| Need number of rows after a buffered SELECT | cursor.rowcount |
| Need only the count of matching database records | SELECT COUNT(*) |
| Need rows changed by INSERT, UPDATE or DELETE | cursor.rowcount |
SELECT * and transfer many records from MySQL only to count them in Python when a SQL COUNT(*) query can return the count directly.For an INSERT statement, rowcount reports the number of rows inserted by the operation.
sql='''INSERT INTO student
(id, name, class, mark, sex)
VALUES (%s, %s, %s, %s, %s)'''
data=(36, 'King', 'Five', 45, 'male')
my_cursor.execute(sql, data)
print('Rows added =', my_cursor.rowcount)
my_connect.commit()
Sample Output
Rows added = 1
For an UPDATE statement, rowcount reports the rows affected by the statement.
sql='UPDATE student SET class=%s WHERE class=%s'
my_cursor.execute(sql, ('Five', 'Four'))
print('Rows updated =', my_cursor.rowcount)
my_connect.commit()
Sample Output
Rows updated = 9
The result depends on the current contents of the table.
rowcount as a substitute for a separate business-rule count when that distinction matters.For a DELETE statement, rowcount reports the number of deleted rows.
sql='DELETE FROM student WHERE class=%s'
my_cursor.execute(sql, ('Five',))
print('Rows deleted =', my_cursor.rowcount)
my_connect.commit()
Sample Output
Rows deleted = 11
WHERE condition before executing the query.Values should normally be passed separately from the SQL statement rather than concatenated into the query string.
Use:
sql='SELECT * FROM student WHERE class=%s'
my_cursor.execute(sql, ('Five',))
The comma is required because a one-item Python tuple is written as:
('Five',)
Avoid constructing queries like:
# Do not build SQL from untrusted input this way
sql="SELECT * FROM student WHERE class='" + user_value + "'"
Parameterized execution lets MySQL Connector/Python safely bind values to placeholders.
INSERT, UPDATE and DELETE commonly require commit() when transaction autocommit is not enabled.
my_cursor.execute(sql, data)
print(my_cursor.rowcount)
my_connect.commit()
rowcount describes the result of the executed statement. commit() makes the transaction permanent.
If the transaction is rolled back later, seeing a positive rowcount does not mean that the change was permanently stored.
After completing the database work:
my_cursor.close()
my_connect.close()
| Statement / Cursor | rowcount Behaviour |
|---|---|
Buffered SELECT | Total returned rows available after execute() |
Non-buffered SELECT before fetch | -1 |
Non-buffered SELECT while fetching | Increases as rows are fetched |
Non-buffered SELECT after all rows fetched | Total number fetched |
INSERT | Number of rows inserted |
UPDATE | Number of rows affected according to MySQL affected-row semantics |
DELETE | Number of rows deleted |
cursor.rowcount is a read-only cursor property.SELECT, it gives the number of returned rows immediately after execution.SELECT, rowcount initially returns -1.COUNT(*).INSERT, rowcount reports rows inserted.UPDATE, it reports affected rows according to MySQL's affected-row behaviour.DELETE, it reports deleted rows.commit() to make data-changing transactions permanent when autocommit is disabled.rowcount does not itself mean a transaction was committed.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.