63

Is there a way to retrieve SQL result column value using column name instead of column index in Python? I'm using Python 3 with mySQL. The syntax I'm looking for is pretty much like the Java construct:

Object id = rs.get("CUSTOMER_ID"); 

I've a table with quite a number of columns and it is a real pain to constantly work out the index for each column I need to access. Furthermore the index is making my code hard to read.

Thanks!

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
Thomas
  • 766
  • 1
  • 6
  • 11
  • You may want to provide more details like some code you are trying, python package you are using. – Shekhar Apr 17 '12 at 16:27
  • For more information about `cursor.description`, see [cursor.description](https://www.python.org/dev/peps/pep-0249/#description) – Cheney Jun 12 '18 at 03:40

11 Answers11

98

The MySQLdb module has a DictCursor:

Use it like this (taken from Writing MySQL Scripts with Python DB-API):

cursor = conn.cursor(MySQLdb.cursors.DictCursor)
cursor.execute("SELECT name, category FROM animal")
result_set = cursor.fetchall()
for row in result_set:
    print "%s, %s" % (row["name"], row["category"])

edit: According to user1305650 this works for pymysql as well.

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
  • 12
    Tried this and it doesn't work too - got an error "TypeError: tuple indices must be integers, not str" – Thomas Apr 17 '12 at 16:54
  • 4
    Are you using the `MySQLdb` module? Did you create your cursor exactly like this: `cursor = conn.cursor(MySQLdb.cursors.DictCursor)`? – Steven Rumbalski Apr 17 '12 at 16:57
  • 1
    my bad! I didn't create the cursor as per your post. It works now - I just need to change MySQLdb.cursors.DictCursor to pymysql.cursors.DictCursor because I use pymysql. Thanks! – Thomas Apr 17 '12 at 17:07
  • Excellent. You can accept this answer by pressing the checkmark to the the left. If you really like it you can also add an upvote. :) – Steven Rumbalski Apr 17 '12 at 17:14
  • I've accepted the answer, unfortunately I don't have the minimum reputation to upvote it :( Thanks again! – Thomas Apr 17 '12 at 17:17
  • How to this with SQLite? – Behnam Jun 06 '17 at 05:48
  • 2
    its actually alot simpler than this, you dont need any different modules: https://stackoverflow.com/a/56209874/1164342 – Hayden Thring Jul 01 '19 at 23:09
  • Since you already know the two columns that are coming back, you could skip using the DictCursor and just do `name, category = row`. DictCursor makes since if you're selecting a lot of columns though. – Hayden Apr 20 '21 at 13:25
  • @Hayden From the question "I've a table with quite a number of columns and it is a real pain to constantly work out the index for each column I need to access." – Steven Rumbalski Apr 21 '21 at 15:12
  • cursor.fetchall() worked with psycopg2. Thanks – nadya Jun 16 '21 at 17:25
34

This post is old but may come up via searching.

Now you can use mysql.connector to retrive a dictionary as shown here: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursordict.html

Here is the example on the mysql site:

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']))
voam
  • 1,006
  • 13
  • 24
22

you must look for something called " dictionary in cursor "

i'm using mysql connector and i have to add this parameter to my cursor , so i can use my columns names instead of index's

db = mysql.connector.connect(
    host=db_info['mysql_host'],
    user=db_info['mysql_user'],
    passwd=db_info['mysql_password'],
    database=db_info['mysql_db'])

cur = db.cursor()

cur = db.cursor( buffered=True , dictionary=True)
Mohammed Breky
  • 385
  • 3
  • 9
16

import pymysql

# Open database connection
db = pymysql.connect("localhost","root","","gkdemo1")

# prepare a cursor object using cursor() method
cursor = db.cursor()

# execute SQL query using execute() method.
cursor.execute("SELECT * from user")

# Get the fields name (only once!)
field_name = [field[0] for field in cursor.description]

# Fetch a single row using fetchone() method.
values = cursor.fetchone()

# create the row dictionary to be able to call row['login']
**row = dict(zip(field_name, values))**

# print the dictionary
print(row)

# print specific field
print(**row['login']**)

# print all field
for key in row:
    print(**key," = ",row[key]**)

# close database connection
db.close()
GK10
  • 343
  • 4
  • 10
7
import mysql
import mysql.connector

db = mysql.connector.connect(
   host = "localhost",
    user = "root",
    passwd = "P@ssword1",
    database = "appbase"
)

cursor = db.cursor(dictionary=True)

sql = "select Id, Email from appuser limit 0,1"
cursor.execute(sql)
result = cursor.fetchone()

print(result)
# output =>  {'Id': 1, 'Email': 'me@gmail.com'}

print(result["Id"])
# output => 1

print(result["Email"])
# output => me@gmail.com
Irfan Ashraf
  • 2,430
  • 21
  • 20
6

python 2.7

import pymysql

conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='password', db='sakila')

cur = conn.cursor()

n = cur.execute('select * from actor')
c = cur.fetchall()

for i in c:
    print i[1]
logi-kal
  • 7,107
  • 6
  • 31
  • 43
Bala Sundaram
  • 79
  • 1
  • 3
3

Of course there is. In Python 2.7.2+...

import MySQLdb as mdb
con =  mdb.connect('localhost', 'user', 'password', 'db');
cur = con.cursor()
cur.execute('SELECT Foo, Bar FROM Table')
for i in range(int(cur.numrows)):
    foo, bar = cur.fetchone()
    print 'foo = %s' % foo
    print 'bar = %s' % bar
TaoJoannes
  • 594
  • 5
  • 14
  • 1
    What do you think he's trying to do? Select the values by column name and assign them to variables seems pretty straight forward. – TaoJoannes Apr 17 '12 at 16:39
  • It looks like he wants a solution that's independent of column order. – Steven Rumbalski Apr 17 '12 at 16:53
  • this works too but it just proliferates my code with all the additional variables. I think the previous post by Steven Rumbalski is a better solution. Anyway thanks for your solution too. – Thomas Apr 17 '12 at 17:10
2

selecting values from particular column:

import pymysql
db = pymysql.connect("localhost","root","root","school")
cursor=db.cursor()
sql="""select Total from student"""
l=[]
try:
    #query execution
    cursor.execute(sql)
    #fetch all rows 
    rs = cursor.fetchall()
    #iterate through rows
    for i in rs:
        #converting set to list
        k=list(i)
        #taking the first element from the list and append it to the list
        l.append(k[0])
    db.commit()
except:
    db.rollback()
db.close()
print(l)
1

You didn't provide many details, but you could try something like this:

# conn is an ODBC connection to the DB
dbCursor = conn.cursor()
sql = ('select field1, field2 from table') 
dbCursor = conn.cursor()
dbCursor.execute(sql)
for row in dbCursor:
    # Now you should be able to access the fields as properties of "row"
    myVar1 = row.field1
    myVar2 = row.field2
conn.close()
Diego
  • 7,312
  • 5
  • 31
  • 38
  • sorry, it doesn't work. Though I'm unsure if it is because mySQL implementation or just DB-API-2.0 lack of support it. – Thomas Apr 17 '12 at 16:51
  • Have you tried using pyodbc? It should be generic and support the same interface for every database. – Diego Apr 17 '12 at 18:25
1

Dictionary Cursor might save your day

cursor = db.cursor(dictionary=True)
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Aung Ko Man
  • 502
  • 6
  • 13
0
import mysql.connector as mysql
...
cursor = mysql.cnx.cursor()
cursor.execute('select max(id) max_id from ids')
(id) = [ id for id in cursor ]
Johan Snowgoose
  • 386
  • 3
  • 6
  • Or even more concise the last line could be id = [ id for id in cursor ][0][0] – Johan Snowgoose Mar 25 '19 at 21:21
  • 1
    Welcome to Stack Overflow. While this command may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. [How to Answer](https://stackoverflow.com/help/how-to-answer) – Popo Mar 25 '19 at 22:01