MySQL: obtenir le nom de la colonne ou l'alias de la requête

Je ne demande pas le SHOW COLUMNS la commande.

je veux créer une application qui fonctionne de la même manière que heidisql, où vous pouvez spécifier une requête SQL et une fois exécutée, renvoie un ensemble de résultats avec des lignes et des colonnes représentant le résultat de votre requête. Les noms de colonnes dans le jeu de résultats doivent correspondre à vos colonnes sélectionnées telles que définies dans votre requête SQL.

dans mon programme Python (en utilisant MySQLdb) ma requête renvoie seulement les résultats de ligne et de colonne, mais pas les noms de colonne. Dans dans l'exemple suivant, les noms de colonne seraient ext,totalsize et filecount. Le SQL serait éventuellement externe du programme.

la seule façon que je peux imaginer pour faire ce travail, est d'écrire ma propre logique D'analyseur SQL pour extraire les noms de colonne sélectionnés.

y a-t-il un moyen facile d'obtenir les noms de colonne pour le SQL fourni? Ensuite, je vais avoir besoin de savoir combien de colonnes la requête retourne-t-elle?

# 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 %sn" % (row[0], row[1], row[2])

cursor.close()
db.close()      
43
demandé sur Eugene 2011-02-16 01:01:17

7 réponses

curseur.description vous donnera un tuple de tuples où [0] pour chacun est l'en-tête de colonne.

num_fields = len(cursor.description)
field_names = [i[0] for i in cursor.description]
174
répondu user625477 2011-02-20 18:13:48

c'est la même chose que thereeman mais plus de manière pythonique en utilisant la compréhension des listes et des dictionnaires

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

pprint.pprint(result)
20
répondu James 2013-02-23 19:23:03

comme @James answer, une façon plus pythonique peut être:

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

Vous pouvez obtenir une seule colonne avec la carte sur le résultat:

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

ou filtrer les résultats:

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

ou d'accumuler des valeurs filtrées colonnes:

totalTxtSize = reduce(
        lambda x,y: x+y,
        filter(lambda x: x['ext'].lower() == 'txt', result)
)
10
répondu juandesant 2013-07-08 18:59:35

je pense que cela devrait faire ce que vous avez besoin (s'appuie sur la réponse ci-dessus) . Je suis sûr qu'il y a une façon plus pythonique de l'écrire, mais vous devriez avoir l'idée générale.

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)
6
répondu thefreeman 2012-12-25 05:15:35

vous pouvez aussi utiliser MySQLdb.cursors.DictCursor. Cela transforme votre ensemble de résultats en une liste de dictionnaires python, bien qu'il utilise un curseur spécial, donc techniquement moins portable que la réponse acceptée. Pas sûr au sujet de la vitesse. Voici le code original modifié qui utilise ceci.

#!/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()  

les fonctions du dictionnaire Standard s'appliquent, par exemple,len(row[0]) pour compter le nombre de colonnes de la première ligne, list(row[0]) pour une liste de noms de colonnes (pour la première ligne), etc. Espérons que cette aide!

4
répondu Eugene 2016-11-01 22:56:17

on dirait que MySQLdb ne fournit pas de traduction pour cet appel API. L'appel C API pertinent est mysql_fetch_fields et il n'y a pas de traduction MySQLdb pour cela

2
répondu Daniel DiPaolo 2011-02-15 22:09:54

Ce n'est qu'un add-on pour la accepté de répondre:

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 est:

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

cela vous permettra d'accéder plus facilement aux valeurs par noms de colonnes.

Supposons que vous avez un user tableau avec des colonnes name et email:

cursor.execute('select * from users')
results = get_results(cursor)
for res in results:
  print(res.name, res.email)
0
répondu MikeL 2018-09-14 20:56:09