it-swarm-ru.tech

MySQL: получить имя столбца или псевдоним из запроса

Я не прошу команду SHOW COLUMNS.

Я хочу создать приложение, которое работает аналогично heidisql, где вы можете указать SQL-запрос и при его выполнении возвращает набор результатов со строками и столбцами, представляющими ваш запрос. Имена столбцов в наборе результатов должны соответствовать выбранным столбцам, как определено в вашем запросе SQL.

В моей программе на Python (с использованием MySQLdb) мой запрос возвращает только результаты строк и столбцов, но не имена столбцов. В следующем примере имена столбцов будут ext, totalsize и filecount. SQL в конечном итоге будет внешним по отношению к программе. 

Единственный способ понять, как это сделать, - написать собственную логику синтаксического анализатора SQL для извлечения названий выбранных столбцов.

Есть ли простой способ получить имена столбцов для предоставленного SQL? Далее мне нужно знать, сколько столбцов возвращает запрос?

# Python

import MySQLdb

#===================================================================
# connect to mysql
#===================================================================

try:
    db = MySQLdb.connect(Host="myhost", user="myuser", passwd="mypass",db="mydb")
except MySQLdb.Error, e:
    print "Error %d: %s" % (e.args[0], e.args[1])
    sys.exit (1)

#===================================================================
# query select from table
#===================================================================

cursor = db.cursor ()   

cursor.execute ("""\
     select ext,
        sum(size) as totalsize,
        count(*) as filecount
     from fileindex
    group by ext
    order by totalsize desc;
""")

while (1):
    row = cursor.fetchone ()
    if row == None:
        break
    print "%s %s %s\n" % (row[0], row[1], row[2])

cursor.close()
db.close()      
47
panofish

cursor.description даст вам кортеж кортежей, где [0] для каждого является заголовком столбца.

num_fields = len(cursor.description)
field_names = [i[0] for i in cursor.description]
183
user625477

Это то же самое, что и thefreeman, но в большей степени Pythonic с использованием списка и словаря 

columns = cursor.description 
result = [{columns[index][0]:column for index, column in enumerate(value)} for value in cursor.fetchall()]

pprint.pprint(result)
22
James

Подобно ответу @James, более Pythonic способ может быть:

fields = map(lambda x:x[0], cursor.description)
result = [dict(Zip(fields,row))   for row in cursor.fetchall()]

Вы можете получить один столбец с картой на результат:

extensions = map(lambda x: x['ext'], result)

или отфильтровать результаты:

filter(lambda x: x['filesize'] > 1024 and x['filesize'] < 4096, result)

или накапливать значения для отфильтрованных столбцов:

totalTxtSize = reduce(
        lambda x,y: x+y,
        filter(lambda x: x['ext'].lower() == 'txt', result)
)
10
juandesant

Я думаю, что это должно делать то, что вам нужно (опирается на ответ выше). Я уверен, что есть более питонский способ написать это, но вы должны получить общее представление.

cursor.execute(query)
columns = cursor.description
result = []
for value in cursor.fetchall():
    tmp = {}
    for (index,column) in enumerate(value):
        tmp[columns[index][0]] = column
    result.append(tmp)
pprint.pprint(result)
7
thefreeman

Вы также можете использовать MySQLdb.cursors.DictCursor. Это превращает ваш набор результатов в список python словарей python, хотя он использует специальный курсор, таким образом технически менее переносимый, чем принятый ответ. Не уверен насчет скорости. Вот отредактированный оригинальный код, который использует это.

#!/usr/bin/python -u

import MySQLdb
import MySQLdb.cursors

#===================================================================
# connect to mysql
#===================================================================

try:
    db = MySQLdb.connect(Host='myhost', user='myuser', passwd='mypass', db='mydb', cursorclass=MySQLdb.cursors.DictCursor)
except MySQLdb.Error, e:
    print 'Error %d: %s' % (e.args[0], e.args[1])
    sys.exit(1)

#===================================================================
# query select from table
#===================================================================

cursor = db.cursor()

sql = 'SELECT ext, SUM(size) AS totalsize, COUNT(*) AS filecount FROM fileindex GROUP BY ext ORDER BY totalsize DESC;'

cursor.execute(sql)
all_rows = cursor.fetchall()

print len(all_rows) # How many rows are returned.
for row in all_rows: # While loops always make me shudder!
    print '%s %s %s\n' % (row['ext'], row['totalsize'], row['filecount'])

cursor.close()
db.close()  

Стандартные функции словаря применяются, например, len(row[0]) для подсчета количества столбцов для первой строки, list(row[0]) для списка имен столбцов (для первой строки) и т.д. Надеюсь, это поможет!

4
Eugene

Похоже, MySQLdb на самом деле не предоставляет перевод для этого вызова API. Соответствующим вызовом C API является mysql_fetch_fields , и для этого нет перевода MySQLdb

2
Daniel DiPaolo

Пытаться:

cursor.column_names

версия соединителя mysql:

mysql.connector.__version__
'2.2.9'
1
Amin

Это только дополнение к принятому ответу:

def get_results(db_cursor):
    desc = [d[0] for d in db_cursor.description]
    results = [dotdict(dict(Zip(desc, res))) for res in db_cursor.fetchall()]
    return results

где dotdict - это:

class dotdict(dict):
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

Это позволит вам гораздо проще получить доступ к значениям по именам столбцов.
Предположим, у вас есть таблица user со столбцами name и email:

cursor.execute('select * from users')
results = get_results(cursor)
for res in results:
  print(res.name, res.email)
0
MikeL