I'm attempting to run some MySQL queries and output the results in my Python program. I've created this function that is called and the cursor is passed through. However, I am running into a problem where running the below code will always return None / nothing.
Here is what I have:
def showInformation(cursor):
number_rows = 'SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = "DB"'
testing = cursor.execute(number_rows)
print(testing)
When using the cursor object itself, I do not run into any problems:
for row in cursor:
print(row)
I guess you need:
print(cursor.fetchone())
because you are returning only a count and so you expect one row.
Calling execute is not supposed to return anything unless multi=True is specified according to mysql documentation. The programmer can only iterate the cursor like you did, or call fetchone to retrieve one row or call fetchall to retrieve all rows or call fetchmany to retrieve some rows.
Related
I have a procedure that returns a recordset using the cursor method:
CREATE OR REPLACE PROCEDURE myschema.permissions_sp(rs_out INOUT refcursor)
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
OPEN rs_out FOR select schema_name,schema_owner,grantee_type,grantee,p_usage,p_create,object_name,perms,p_select,p_update,p_insert,p_delete,p_truncate,p_references,p_trigger,p_rule from xxxx.myview;
END;
$$
/
GRANT EXECUTE on PROCEDURE myschema.permissions_sp(INOUT refcursor) TO xxxx_user
/
And I can call it perfectly fine from workbench using my admin login.
BEGIN;
CALL meta.permissions_sp('apples');
COMMIT;
Result is a dataset of 16columns x >7k rows
(To be honest I don't even need to do the transaction parts, it'll run just fine with the CALL only)
However, when I call it via psycopg2, this is what happens :
cur = conn.cursor()
cur.execute("CALL meta.permissions_sp('apples');")
conn.commit()
rows = cur.fetchall()
print('rows:%s' % (rows))
Output:
> rows:[('apples',)]
I've played around with using the commit and not using it.
Just really struggling to understand what is going on.
At this stage not sure if it's how I'm calling from Python, or on the Redshift side of things.
Any guidance appreciated !
The procedure receives a name as its argument and returns a server-side cursor with that name. On the client side, after calling the procedure you must declare a named cursor with the same name and use it to access the query results. You must do this before committing the connection, otherwise the server-side cursor will be destroyed.
with psycopg2.connect(dbname='test') as conn:
cur = conn.cursor()
cur.execute("""CALL myschema.permissions_sp('mycursor')""")
# Use the name that was passed to the procedure.
named_cursor = conn.cursor('mycursor')
for row in named_cursor.fetchall():
print(row)
This is analogous to how you might get the results in the psql console, as described in the Redshift docs:
BEGIN;
CALL myschema.permissions_sp('mycursor');
FETCH ALL FROM mycursor;
COMMIT;
This is the reproduced sample:
import mysql.connector
conn = mysql.connector.connect(
user='root', password='12347',
host='localhost')
def getCursor():
return conn.cursor()
def execQuery(cursor=getCursor()):
cursor.execute("SELECT 2")
cursor.fetchall()
cursor.close()
for i in range(4):
cursor = execQuery()
This code works without cursor.close(). But what I find weird is that this sample works even with cursor.close() with a simple change:
def execQuery():
cursor=getCursor()
cursor.execute("SELECT 2")
cursor.fetchall()
cursor.close()
By moving the default parameter to the body of the function.
I don't know if it's the best practice to close the cursor, so I can skip closing cursor while keeping the first form. If it's not the best practice to have a default parameter that uses return value of a function, I can go with the second form. But I want to why they act differently
It's like I'm having the same error as the following:
cursor.execute("SELECT 2")
cursor.fetchall()
cursor.close()
cursor.execute("SELECT 2")
It's like every call of execQuery is using the same cursor, so it gets blocked right at the second call.
When you need to connect to Database you need something like cursor. You need a cursor object to fetch results.
In the sample program when you run loop in range (4) it calls execQuery() . Looking into definition you can find def execQuery(cursor=getCursor()): the function takes input as cursor and by default it used getCursor() function which creates cursor everything when the loop is executed.
While in your program you are closing the cursor but not creating it again hence when second execute query comes there is no cursor present and the program throws an error.
I'm trying to get a cursor from stored procedure in txpostgres.
Psycopg2 has a named cursors which are working fine for it. But there is no curs = conn.cursor('name') statement in txpostgres.
Is there another way to get it ?
txpostgres doesn't have a named cursor feature. However, psycopg2's named cursors are just a convenience wrapper for PostgreSQL's cursors. I don't have much experience with stored procedures, but here's an example with a simple query:
#inlineCallbacks
def transaction(cursor):
yield cursor.execute('mycursor CURSOR FOR SELECT bigtable')
yield cursor.execute('FETCH ALL FROM mycursor')
data = yield cursor.fetchall()
conn.runInteraction(transaction)
I'm writing a python CGI script that will query a MySQL database. I'm using the MySQLdb module. Since the database will be queryed repeatedly, I wrote this function....
def getDatabaseResult(sqlQuery,connectioninfohere):
# connect to the database
vDatabase = MySQLdb.connect(connectioninfohere)
# create a cursor, execute and SQL statement and get the result as a tuple
cursor = vDatabase.cursor()
try:
cursor.execute(sqlQuery)
except:
cursor.close()
return None
result = cursor.fetchall()
cursor.close()
return result
My question is... Is this the best practice? Of should I reuse my cursor within my functions? For example. Which is better...
def callsANewCursorAndConnectionEachTime():
result1 = getDatabaseResult(someQuery1)
result2 = getDatabaseResult(someQuery2)
result3 = getDatabaseResult(someQuery3)
result4 = getDatabaseResult(someQuery4)
or do away with the getDatabaseeResult function all together and do something like..
def reusesTheSameCursor():
vDatabase = MySQLdb.connect(connectionInfohere)
cursor = vDatabase.cursor()
cursor.execute(someQuery1)
result1 = cursor.fetchall()
cursor.execute(someQuery2)
result2 = cursor.fetchall()
cursor.execute(someQuery3)
result3 = cursor.fetchall()
cursor.execute(someQuery4)
result4 = cursor.fetchall()
The MySQLdb developer recommends building an application specific API that does the DB access stuff for you so that you don't have to worry about the mysql query strings in the application code. It'll make the code a bit more extendable (link).
As for the cursors my understanding is that the best thing is to create a cursor per operation/transaction. So some check value -> update value -> read value type of transaction could use the same cursor, but for the next one you would create a new one. This is again pointing to the direction of building an internal API for the db access instead of having a generic executeSql method.
Also remember to close your cursors, and commit changes to the connection after the queries are done.
Your getDatabaseResult function doesn't need to have a connect for every separate query though. You can share the connection between the queries as long as you act responsible with the cursors.
When the following code is executed:
q = MyKind.all()
taskqueue.add(url="/admin/build", params={'cursor': q.cursor()})
I get:
AssertionError: No cursor available.
Why does this happen? Do I need to fetch something first? (I'd rather not; the code is cleaner just to get the query and pass it on.)
I'm using Python on Google App Engine 1.3.5.
Yes, a cursor is only available if you've fetched something; there's no cursor for the first result in the query.
As a workaround, you could wrap the call to cursor() in a try/except and pass on None to the next task if there isn't a cursor available.