2009-02-23 2 views
11

У меня есть код, который я использовал для запроса MySQL, и я надеюсь использовать его с SQLite. Моя реальная надежда состоит в том, что это не будет включать внесение слишком большого количества изменений в код. К сожалению, следующий код не работает с SQLite:Как я могу ссылаться на столбцы по их именам в python, вызывающем SQLite?

cursor.execute(query) 

rows = cursor.fetchall() 

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

Это дает следующее сообщение об ошибке:

TypeError: tuple indices must be integers 

Принимая во внимание, если изменить ссылку, чтобы использовать номер столбца, он отлично работает:

data.append(row[1]) 

Можно ли выполнить запрос таким образом, чтобы я мог ссылаться на столбцы по их именам?

ответ

11

Я не уверен, если это лучший подход, но вот то, что я обычно делаю, чтобы получить запись установить с помощью совместимого модуля с DB-API 2:

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) 

Метод форматирования запроса является одним из стандарты DB-API, но, по-видимому, это предпочтительный метод Psycopg2; другие адаптеры DB-API могут предложить другое соглашение, которое будет хорошо.

Написание таких запросов, когда неявная распаковка кортежей используется для работы с результирующим набором, как правило, была более эффективной для меня, чем пытаться беспокоиться о совпадении имен переменных Python с именами столбцов SQL (которые я обычно использую только для удаления префиксы, а затем только в том случае, если я работаю с подмножеством имен столбцов, так что префиксы больше не помогают прояснить ситуацию) и много лучше, чем помнить идентификаторы числовых столбцов.

Этот стиль также поможет вам избежать SELECT * FROM table..., что является просто катастрофой обслуживания для чего угодно, кроме простейших таблиц и запросов.

Итак, не совсем тот ответ, о котором вы просили, но, возможно, просвещающий тем не менее.

+0

На самом деле, это прекрасно! Спасибо. – Ben

+0

К сожалению: следовало бы проверить более тщательно. Это не работает. С SQLite foo в конечном итоге становится чем-то вроде (123), а с MySQL он заканчивается ('foo': 123) – Ben

+0

Получение подобных результатов заставляет задуматься, совместим ли ваш модуль MySQL с DB-API 2.0 ... если он не, попытка заменить другой модуль базы данных будет уродливой. Какой модуль MySQL вы используете? – kquinn

13

Чтобы получить доступ к столбцам по имени, используйте атрибут row_factory экземпляра Connection. Он позволяет вам установить функцию, которая принимает аргументы cursor и row, и возвращает все, что угодно. Есть несколько встроенных в pysqlite, а именно sqlite3.Row, который делает то, что вы просили.

+0

В документации: http://docs.python.org/library/sqlite3.html#accessing-columns-by-name-instead-of-by-index – chaimp

1

SQLite API поддерживает cursor.description, так что вы можете легко сделать это, как этот

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']]) 

Немного долго наматывается, но получает работу. Я заметил, что они даже имеют его в файле factory.py в файле dict_factory.

1

ответ Kushal на this forum работает отлично:

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'] 

Обратите внимание, что имя столбца чувствительно к регистру.

+1

Такой стыд, что этот ответ противоречит неправильному вопросу (sqlite, а не mysql), поскольку он отлично ответил на мою проблему. –

11

В течение пяти лет с тех пор, как вопрос был задан, а затем ответил, возникло очень простое решение. Любой новый код может просто обернуть объект соединения строкой. Пример кода:

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']) 

Вот fine docs. Наслаждайтесь!

+0

Тот же ответ был отправлен за 2 года до этого ответа. – 7stud

Смежные вопросы