2011-02-15 19 views
38

No estoy pidiendo el comando SHOW COLUMNS.MySQL: Obtener el nombre de columna o el alias de la consulta

Quiero crear una aplicación que funcione de manera similar a heidisql, donde puede especificar una consulta SQL y cuando se ejecuta, devuelve un conjunto de resultados con filas y columnas que representan el resultado de su consulta. Los nombres de columna en el conjunto de resultados deben coincidir con las columnas seleccionadas, tal como se define en su consulta SQL.

En mi programa de Python (usando MySQLdb) mi consulta devuelve solo los resultados de fila y columna, pero no los nombres de columna. En el siguiente ejemplo, los nombres de columna serían ext, totalsize y filecount. El SQL eventualmente sería externo al programa.

La única manera en que me puedo imaginar para hacer esto, es escribir mi propia lógica de analizador SQL para extraer los nombres de columna seleccionados.

¿Hay alguna manera fácil de obtener los nombres de columna para el SQL proporcionado? Siguiente ¿Necesitaré saber cuántas columnas devuelve la consulta?

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

Gracias Daniel DiPaulo ... esa es la respuesta que estaba buscando.Acabo de escribir mi propio analizador SQL para poder extraer los nombres/alias de las columnas de selección. Funciona bien. – panofish

+0

Gracias al usuario625477 ... esa es la mejor respuesta. ¿Por qué stackoverflow no me envió por correo electrónico las respuestas actualizadas? – panofish

Respuesta

153

cursor.description le dará una tupla de tuplas donde [0] para cada una es el encabezado de la columna.

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

¿Por qué esta respuesta no está marcada como correcta? Esto es claramente lo que necesita el OP. – thefreeman

+0

Nunca recibí un correo electrónico de la respuesta actualizada. – panofish

+0

¡Eres mi héroe! – Pontios

5

Creo que esto debería hacer lo que necesita (se basa en la respuesta anterior). Estoy seguro de que hay una forma más pitón de escribirlo, pero debes tener una idea general.

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) 
15

Esto es lo mismo que thefreeman pero más en forma Pythonic utilizando el diccionario de lista y la comprensión

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

pprint.pprint(result) 
9

similares a la respuesta @ James, de una manera más Pythonic puede ser:

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

Puede obtener una sola columna con el mapa sobre el resultado:

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

o filtrar los resultados:

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

o se acumulan los valores para las columnas filtradas:

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

Completo. ¿Hay alguna ventaja de usar fetchall sobre iterar en el cursor? –

+0

@kzarns: Diría que hacer el ejemplo más corto y obtener una lista completa. En su lugar, puede crear una función de generador que itere sobre el cursor, usando 'yield', y podría usar menos memoria. – juandesant

2

También es posible usar MySQLdb.cursors.DictCursor. Esto convierte su conjunto de resultados en una lista de python de diccionarios de Python, aunque utiliza un cursor especial, por lo que técnicamente es menos portátil que la respuesta aceptada. No estoy seguro acerca de la velocidad. Aquí está el código original editado que usa esto.

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

estándar Las funciones del diccionario se aplican, por ejemplo, len(row[0]) para contar el número de columnas de la primera fila, list(row[0]) para obtener una lista de nombres de columna (para la primera fila), etc. Esperamos que esto ayude!

+0

Buen punto, pero estaba escribiendo una utilidad donde la consulta varía y necesito apoyar el orden de campo en la consulta. El cursor del diccionario no ordena a los campos. – panofish

Cuestiones relacionadas