简体   繁体   中英

How can I reference columns by their names in python calling SQLite?

I have some code which I've been using to query MySQL, and I'm hoping to use it with SQLite. My real hope is that this will not involve making too many changes to the code. Unfortunately, the following code doesn't work with SQLite:

cursor.execute(query)

rows = cursor.fetchall()

data = []
for row in rows
  data.append(row["column_name"])

This gives the following error:

 TypeError: tuple indices must be integers

Whereas if I change the reference to use a column number, it works fine:

  data.append(row[1])

Can I execute the query in such a way that I can reference columns by their names?

In the five years since the question was asked and then answered, a very simple solution has arisen. Any new code can simply wrap the connection object with a row factory. Code example:

import sqlite3

conn = sqlite3.connect('./someFile')
conn.row_factory = sqlite3.Row        // Here's the magic!

cursor = conn.execute("SELECT name, age FROM someTable")
for row in cursor:
    print(row['name'])

Here are some fine docs . Enjoy!

To access columns by name, use the row_factory attribute of the Connection instance. It lets you set a function that takes the arguments cursor and row , and return whatever you'd like. There's a few builtin to pysqlite, namely sqlite3.Row , which does what you've asked.

I'm not sure if this is the best approach, but here's what I typically do to retrieve a record set using a DB-API 2 compliant module:

cursor.execute("""SELECT foo, bar, baz, quux FROM table WHERE id = %s;""", 
                  (interesting_record_id,))

for foo, bar, baz, quux in cursor.fetchall():
    frobnicate(foo + bar, baz * quux)

The query formatting method is one of the DB-API standards, but happens to be the preferred method for Psycopg2; other DB-API adapters might suggest a different convention which will be fine.

Writing queries like this, where implicit tuple unpacking is used to work with the result set, has typically been more effective for me than trying to worry about matching Python variable names to SQL column names (which I usually only use to drop prefixes, and then only if I'm working with a subset of the column names such that the prefixes don't help to clarify things anymore), and is much better than remembering numerical column IDs.

This style also helps you avoid SELECT * FROM table... , which is just a maintenance disaster for anything but the simplest tables and queries.

So, not exactly the answer you were asking for, but possibly enlightening nonetheless.

This can be done by adding a single line after the "connect" statment:

conn.row_factory = sqlite3.Row

Check the documentation here: http://docs.python.org/library/sqlite3.html#accessing-columns-by-name-instead-of-by-index

kushal's answer to this forum works fine:

Use a DictCursor:

import MySQLdb.cursors

.
.
.
cursor = db.cursor (MySQLdb.cursors.DictCursor)
cursor.execute (query)
rows = cursor.fetchall ()

for row in rows:
print row['employee_id'] 

Please take note that the column name is case sensitive.

The SQLite API supports cursor.description so you can easily do it like this

headers = {}
for record in cursor.fetchall():
    if not headers:
        headers = dict((desc[0], idx) for idx,desc in cursor.description))
    data.append(record[headers['column_name']])

A little long winded but gets the job done. I noticed they even have it in the factory.py file under dict_factory.

Use the cursor description, like so:

rows = c.fetchall()
for row in rows:
    for col_i, col in enumerate(row):   
        print("Attribute: {0:30} Value: {1}".format(c.description[col_i][0],col))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM