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()
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]
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)
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)
)
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)
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!
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
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
où 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)