111 votes

MySQL : Obtenir le nom ou l'alias d'une colonne à partir d'une requête

Je ne demande pas la SHOW COLUMNS commandement.

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

Dans mon programme Python (utilisant MySQLdb ), ma requête ne renvoie que les résultats des lignes et des colonnes, mais pas les noms des colonnes. Dans l'exemple suivant, les noms des colonnes seraient ext , totalsize y filecount . Le SQL sera finalement exclu du programme.

Le seul moyen que j'ai trouvé pour que cela fonctionne est d'écrire ma propre logique d'analyseur SQL pour extraire les noms des colonnes sélectionnées.

Existe-t-il un moyen simple d'obtenir les noms des colonnes pour le code SQL fourni ? Ensuite, j'ai besoin de savoir combien de colonnes la requête retourne ?

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

275voto

user625477 Points 2596

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

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

45voto

James Points 937

C'est la même chose que thefreeman mais de façon plus pythonique en utilisant la liste et la compréhension du dictionnaire.

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

pprint.pprint(result)

33voto

juandesant Points 96

Comme pour la réponse de @James, une méthode plus pythonique peut être utilisée :

fields = [field_md[0] for field_md in cursor.description]
result = [dict(zip(fields,row)) for row in cursor.fetchall()]

Vous pouvez obtenir une seule colonne avec une compréhension de liste sur le résultat :

extensions = [row['ext'] for row in result)

ou filtrer les résultats en utilisant un "if" supplémentaire dans la compréhension de la liste :

large = [row for row in result if row['filesize'] > 1024 and row['filesize'] < 4096]

ou accumuler des valeurs pour des colonnes filtrées :

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

13voto

thefreeman Points 526

Je pense que ceci devrait faire ce dont vous avez besoin (en se basant 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)

9voto

Eugene Points 838

Vous pouvez également utiliser MySQLdb.cursors.DictCursor . Cela transforme votre ensemble de résultats en une liste python de dictionnaires python, bien qu'il utilise un curseur spécial, donc techniquement moins portable que la réponse acceptée. Je ne suis pas sûr de la rapidité. Voici le code original édité qui l'utilise.

#!/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 standard du dictionnaire 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. J'espère que cela vous aidera !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X