I am connecting to mysql database via mysql connector and running a simple query to pull a list of IDs. I need to loop over that list and pass them into some other code. For some reason I am getting a list of tuples. Is this expected behavior? If not, what am I doing wrong?
Here is the snippet of my code:
import mysql.connector
conn = mysql.connector.connect(host='127.0.0.1', database='t', user='r', password='pwd')
cursor = conn.cursor()
query = ( "select id from T where updated < '%s'" % (run_date) )
cursor.execute(query)
for row in cursor:
print (row)
cursor.close()
I am getting the following back (from an INT field in d/b):
(Decimal('991837'),)
(Decimal('991838'),)
(Decimal('991839'),)
(Decimal('991871'),)
(Decimal('991879'),)
(Decimal('991899'),)
(Decimal('992051'),)
(Decimal('992299'),)
(Decimal('992309'),)
if you want to access just the data in the row you need to go into the dictionary
first you must make it true in the cursor
cur = db.cursor( buffered=True , dictionary=True)
then the result will be like this :
{'Decimal' : '991837'}
i'm sure the Decimal is your row name
so when you need to access to the value do this
import mysql.connector
conn = mysql.connector.connect(host='127.0.0.1', database='t', user='r', password='pwd')
cursor = conn.cursor()
query = ( "select id from T where updated < '%s'" % (run_date) )
cursor.execute(query)
for row in cursor:
print (row['Decimal'])
cursor.close()
i hope it works for i was looking for this solution for the past 2 days and no answers
the only way i debugged i opened the debugger and print out all the variables
have fun with Python :)
Yes, this is expected behavior. Using the cursor as an iterable is basically equivalent to looping over it using the fetchone() method. From the documentation for fetchone() (emphasis mine):
This method retrieves the next row of a query result set and returns a
single sequence, or None if no more rows are available. By default,
the returned tuple consists of data returned by the MySQL server,
converted to Python objects. If the cursor is a raw cursor, no such
conversion occurs;
Related
I have a Python application, in which I'm calling a MySQL stored procedure from my view, like so:
import mysql.connector
proc = 'audit_report'
parms = [data['schoolid'], dateToISO(data['startdatedefault'],'from'), dateToISO(data['enddatedefault'],'to'), joinIntList(data['studypgms'], joinWith), joinIntList(data['fedpgms'], joinWith), joinIntList(data['statuses'], joinWith), data['fullssndefault']]
conn = mysql.connector.connect(user='usr', database='db', password='pwd')
cursor = conn.cursor(dictionary=True)
cursor.callproc(proc, parms)
for result in cursor.stored_results():
print(result.fetchall())
I am getting the data returned as a list of tuples, the standard output. Since I'm using connector version 2.1.7, the docs say adding
dictionary=True
to the cursor declaration should cause the rowset to be returned as a list of dictionaries, with column name as the key of each dictionary. Main difference between my application and the example in the docs is that I'm using cursor.callproc(), whereas the examples use cursor.execute() with actual sql code.
I tried
print(cursor.column_names)
to see if I could get the column names that way, but all I get is
('#_audit_report_arg1', '#_audit_report_arg2', '#_audit_report_arg3', '#_audit_report_arg4', '#_audit_report_arg5', '#_audit_report_arg6', '#_audit_report_arg7')
which looks more like the input parameters to the stored procedure.
Is there any way to actually get the column names of the returned data? The procedure is somewhat complex and contains crosstab-type manipulation, but calling the same stored procedure from MySQL Workbench happily supplies the column names.
Normally, knowing what the output is supposed to be, I could hard-code column names, except this procedure crosstabs the data for the last few columns, and it is unpredictable what they will be until after the query runs.
Thanks...
You can use pymysql in python3 and it should work fine !!
import pymysql.cursors
connection = pymysql.connect(host='',
user='',
password='',
db='test',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
try:
with connection.cursor() as cursor:
# Read a single record
sql = "query"
cursor.execute(sql)
result = cursor.fetchone()
num_fields = len(cursor.description)
field_names = [i[0] for i in cursor.description]
print (field_names)
finally:
connection.close()
I am trying to fetch data from AWS MariaDB:
cursor = self._cnx.cursor()
stmt = ('SELECT * FROM flights')
cursor.execute(stmt)
print(cursor.rowcount)
# prints 2
for z in cursor:
print(z)
# Does not iterate
row = cursor.fetchone()
# row is None
rows = cursor.fetchall()
# throws 'No result set to fetch from.'
I can verify that table contains data using MySQL Workbench. Am I missing some step?
EDIT: re 2 answers:
res = cursor.execute(stmt)
# res is None
EDIT:
I created new Python project with a single file:
import mysql.connector
try:
cnx = mysql.connector.connect(
host='foobar.rds.amazonaws.com',
user='devuser',
password='devpasswd',
database='devdb'
)
cursor = cnx.cursor()
#cursor = cnx.cursor(buffered=True)
cursor.execute('SELECT * FROM flights')
print(cursor.rowcount)
rows = cursor.fetchall()
except Exception as exc:
print(exc)
If I run this code with simple cursor, fetchall raises "No result set to fetch from". If I run with buffered cursor, I can see that _rows property of cursor contains my data, but fetchall() returns empty array.
Your issue is that cursor.execute(stmt) returns an object with results and you're not storing that.
results = cursor.execute(stmt)
print(results.fetchone()) # Prints out and pops first row
For the future googlers with the same Problem I found a workaround which may help in some cases:
I didn't find the source of the problem but a solution which worked for me.
In my case .fetchone() also returned none whatever I did on my local(on my own Computer) Database. I tried the exact same code with the Database on our companies server and somehow it worked. So I copied the complete server Database onto my local Database (by using database dumps) just to get the server settings and afterwards I also could get data from my local SQL-Server with the code which didn't work before.
I am a SQL-newbie but maybe some crazy setting on my local SQL-Server prevented me from fetching data. Maybe some more experienced SQL-user knows this setting and can explain.
I am retrieving a single row from a single column in my database. The pymssql documentation exclusively uses loops to access the data in a cursor.
conn = pymssql.connect(server, user, password, "tempdb")
cursor = conn.cursor()
cursor.execute('SELECT %s', 'Foo')
#This works but it's ugly
for row in cursor:
print row[0]
break
#The following throws an error
print cursor[0][0]
conn.close()
Is there a way to access the data inside the cursor object without a for loop?
You can use cursor.fetchone()[0] in place of cursor[0][0].
However, if nothing is returned from the query you're going to get an exception. Better to do something "ugly" like this:
row = cursor.fetchone()
if row:
print row[0]
I am trying to use the following additional arguments in the mysql.connector.connect(), however when I run the following code it doesn't seem to have any effect.
import mysql.connector
cnx = mysql.connector.connect(
....
raw='true',
use_unicode='false'
)
cursor = cnx.cursor()
query = ("...")
cursor.execute(query)
result = cursor.fetchall()
print result
[(datetime.date(2015, 4, 5), 1243), ...
where the results has a column of MySQL datetime format values
but even with these arguments the output is still in python datetime.date(YYYY,M,D) format
same issue also when calling col = cursor.column_names, returns unicode instead of strings even though "raw" is set to true.
print cursor.colun_names = (u'string_1', u'string_2')
is there some other configuration needed? i dont want to have to write code to convert these every time its used. thanks!
I think when Python evaluates something like:
if use_unicode:
// do something
Variable use_unicode returns True, because string 'false' evaluated to True. Try to use Boolean values.
import mysql.connector
cnx = mysql.connector.connect(
....
raw=True,
use_unicode=False
)
cursor = cnx.cursor()
query = ("...")
cursor.execute(query)
result = cursor.fetchall()
print result
raw=True means:
A MySQLCursorRaw cursor skips the conversion from MySQL data types to
Python types when fetching rows. A raw cursor is usually used to get
better performance or when you want to do the conversion yourself.
So you get ByteArray as expected. I don't know what exactly you are trying to do, but when I work with MySQL in Python, I prefer to work with dictionary data structure.
cursor = cnx.cursor(dictionary=True)
And then you will get result as dictionary. If you want to view it as string, just do print str(dict)
import mysql.connector
cnx = mysql.connector.connect(user=self.username, password=self.password, host=self.host, database=self.database);
cursor = cnx.cursor(dictionary=True)
query = ("...")
cursor.execute(query)
result = cursor.fetchall()
print str(result)
In Python mysqldb I could declare a cursor as a dictionary cursor like this:
cursor = db.cursor(MySQLdb.cursors.DictCursor)
This would enable me to reference columns in the cursor loop by name like this:
for row in cursor: # Using the cursor as iterator
city = row["city"]
state = row["state"]
Is it possible to create a dictionary cursor using this MySQL connector?
http://dev.mysql.com/doc/connector-python/en/connector-python-example-cursor-select.html
Their example only returns a tuple.
I imagine the creators of MySQL would eventually do this for us?
According to this article it is available by passing in 'dictionary=True' to the cursor constructor:
http://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursordict.html
so I tried:
cnx = mysql.connector.connect(database='bananas')
cursor = cnx.cursor(dictionary=True)
and got:
TypeError: cursor() got an unexpected keyword argument 'dictionary'
and I tried:
cnx = mysql.connector.connect(database='bananas')
cursor = cnx.cursor(named_tuple=True)
and got:
TypeError: cursor() got an unexpected keyword argument 'named_tuple'
and I tried this one too: cursor = MySQLCursorDict(cnx)
but to no avail. Clearly I'm on the wrong version here and I suspect we just have to be patient as the document at http://downloads.mysql.com/docs/connector-python-relnotes-en.a4.pdf suggests these new features are in alpha phase at point of writing.
A possible solution involves subclassing the MySQLCursor class like this:
class MySQLCursorDict(mysql.connector.cursor.MySQLCursor):
def _row_to_python(self, rowdata, desc=None):
row = super(MySQLCursorDict, self)._row_to_python(rowdata, desc)
if row:
return dict(zip(self.column_names, row))
return None
db = mysql.connector.connect(user='root', database='test')
cursor = db.cursor(cursor_class=MySQLCursorDict)
Now the _row_to_python() method returns a dictionary instead of a tuple.
I found this on the mysql forum, and I believe it was posted by the mysql developers themselves. I hope they add it to the mysql connector package some day.
I tested this and it does work.
UPDATE: As mentioned below by Karl M.W... this subclass is no longer needed in v2 of the mysql.connector. The mysql.connector has been updated and now you can use the following option to enable a dictionary cursor.
cursor = db.cursor(dictionary=True)
This example works:
cnx = mysql.connector.connect(database='world')
cursor = cnx.cursor(dictionary=True)
cursor.execute("SELECT * FROM country WHERE Continent = 'Europe'")
print("Countries in Europe:")
for row in cursor:
print("* {Name}".format(Name=row['Name']
Keep in mind that in this example, 'Name' is specific to the column name of the database being referenced.
Also, if you want to use stored procedures, do this instead:
cursor.callproc(stored_procedure_name, args)
result = []
for recordset in cursor.stored_results():
for row in recordset:
result.append(dict(zip(recordset.column_names,row)))
where stored_procedure_name is the name of the stored procedure to use and args is the list of arguments for that stored procedure (leave this field empty like [] if no arguments to pass in).
This is an example from the MySQL documentation found here: http://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursordict.html
Using Python 3.6.2 and MySQLdb version 1.3.10, I got this to work with:
import MySQLdb
import MySQLdb.cursors
...
conn = MySQLdb.connect(host='...',
<connection info>,
cursorclass=MySQLdb.cursors.DictCursor)
try:
with conn.cursor() as cursor:
query = '<SQL>'
data = cursor.fetchall()
for record in data:
... record['<field name>'] ...
finally:
conn.close()
I'm using PyCharm, and simply dug into the MySQLdb modules connections.py and cursors.py.
I had the same problem with the default cursor returning tuples with no column names.
The answer is here:
Getting error while using MySQLdb.cursors.DictCursor in MYSQL_CURSORCLASS
app.config["MYSQL_CURSORCLASS"] = "DictCursor"