I have a sql statement that returns no hits. For example, \'select * from TAB where 1 = 2\'
.
I want to check how many rows are returned,
cu
MySQLdb will not raise an exception if the result set is empty. Additionally cursor.execute() function will return a long value which is number of rows in the fetched result set. So if you want to check for empty results, your code can be re-written as
rows_count = cursor.execute(query_sql)
if rows_count > 0:
rs = cursor.fetchall()
else:
// handle empty result set
I had issues with rowcount always returning -1 no matter what solution I tried.
I found the following a good replacement to check for a null result.
c.execute("SELECT * FROM users WHERE id=?", (id_num,))
row = c.fetchone()
if row == None:
print("There are no results for this query")
cursor.rowcount
will usually be set to 0.
If, however, you are running a statement that would never return a result set (such as INSERT
without RETURNING
, or SELECT ... INTO
), then you do not need to call .fetchall()
; there won't be a result set for such statements. Calling .execute()
is enough to run the statement.
Note that database adapters are also allowed to set the rowcount to -1
if the database adapter can't determine the exact affected count. See the PEP 249 Cursor.rowcount specification:
The attribute is
-1
in case no.execute*()
has been performed on the cursor or the rowcount of the last operation is cannot be determined by the interface.
The sqlite3 library is prone to doing this. In all such cases, if you must know the affected rowcount up front, execute a COUNT()
select in the same transaction first.
For reference, cursor.rowcount
will only return on CREATE
, UPDATE
and DELETE
statements:
| rowcount
| This read-only attribute specifies the number of rows the last DML statement
| (INSERT, UPDATE, DELETE) affected. This is set to -1 for SELECT statements.
Notice: This is for MySQLdb module in Python.
For a SELECT
statement, there shouldn't be an exception for an empty recordset. Just an empty list ([]
) for cursor.fetchall()
and None
for cursor.fetchone()
.
For any other statement, e.g. INSERT
or UPDATE
, that doesn't return a recordset, you can neither call fetchall()
nor fetchone()
on the cursor. Otherwise, an exception will be raised.
There's one way to distinguish between the above two types of cursors:
def yield_data(cursor):
while True:
if cursor.description is None:
# No recordset for INSERT, UPDATE, CREATE, etc
pass
else:
# Recordset for SELECT, yield data
yield cursor.fetchall()
# Or yield column names with
# yield [col[0] for col in cursor.description]
# Go to the next recordset
if not cursor.nextset():
# End of recordsets
return
if you're connecting to a postgres database, the following works:
result = cursor.execute(query)
if result.returns_rows:
# we got rows!
return [{k:v for k,v in zip(result.keys(), r)} for r in result.rows]
else:
return None