MySQL: Obtener nombre de columna o alias de la consulta

No estoy pidiendo el comando SHOW COLUMNS .

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 sus columnas seleccionadas como se define en su consulta SQL.

En mi progtwig 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 las columnas serían ext , totalsize y filecount . El SQL eventualmente sería externo al progtwig.

La única forma que puedo imaginar para hacer que esto funcione, es escribir mi propia lógica del analizador de SQL para extraer los nombres de las columnas seleccionadas.

¿Hay una manera fácil de obtener los nombres de columna para el SQL proporcionado? A continuación, 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() 

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

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

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

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

Similar a la respuesta de @James, una forma más pythonica 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 acumular valores para columnas filtradas:

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

Creo que esto debería hacer lo que necesitas (se basa en la respuesta anterior). Estoy seguro de que hay una forma más python 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) 

También puede usar MySQLdb.cursors.DictCursor . Esto convierte su conjunto de resultados en una lista de diccionarios de python en python, aunque utiliza un cursor especial, por lo tanto, técnicamente menos portátil que la respuesta aceptada. No estoy seguro de la velocidad. Aquí está el código original editado que utiliza 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() 

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

Parece que MySQLdb en realidad no proporciona una traducción para esa llamada a la API. La llamada a la API de C relevante es mysql_fetch_fields , y no hay traducción de MySQLdb para eso

Esto es solo un complemento a la respuesta aceptada:

 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 

donde dotdict es:

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

Esto le permitirá acceder mucho más fácilmente a los valores por nombre de columna.
Supongamos que tiene una tabla de user con name columnas y email :

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