Je ne demande pas la commande SHOW COLUMNS
.
Je souhaite créer une application qui fonctionne de la même manière que heidisql, dans laquelle vous pouvez spécifier une requête SQL et, 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 de colonne 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 (en utilisant MySQLdb
), ma requête renvoie uniquement les résultats des lignes et des colonnes, mais pas les noms de colonne. Dans l'exemple suivant, les noms de colonne seraient ext
, totalsize
et filecount
. Le code SQL serait éventuellement externe au programme.
Le seul moyen que je puisse comprendre pour que cela fonctionne est d'écrire ma propre logique d'analyse SQL pour extraire les noms de colonne sélectionnés.
Existe-t-il un moyen simple d’obtenir les noms de colonne pour le code SQL fourni? Ensuite, j’ai besoin de savoir combien de colonnes la requête renvoie-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 %s\n" % (row[0], row[1], row[2])
cursor.close()
db.close()
curseur.description vous donnera un nuplet de nuplets 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 thefreeman mais plus de façon 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)
Semblable à la réponse @James, une manière 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 map 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 accumuler des valeurs pour les colonnes filtrées:
totalTxtSize = reduce(
lambda x,y: x+y,
filter(lambda x: x['ext'].lower() == 'txt', result)
)
Je pense que cela devrait faire ce dont vous avez besoin (repose sur la réponse ci-dessus). Je suis sûr qu'il y a une manière plus pythonique de l'écrire, mais vous devriez en avoir une 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 également utiliser MySQLdb.cursors.DictCursor
. Cela transforme votre jeu 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. Pas sûr de la vitesse. Voici le code original édité qui utilise cela.
#!/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 de 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. J'espère que cela vous aidera!
On dirait que MySQLdb ne fournit pas de traduction pour cet appel API. L’appel C API approprié est mysql_fetch_fields
, et il n’ya pas de traduction MySQLdb pour cela
Essayer:
cursor.column_names
version du connecteur mysql:
mysql.connector.__version__
'2.2.9'
Ceci n'est qu'un ajout à la réponse acceptée:
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 beaucoup plus facilement aux valeurs par noms de colonnes.
Supposons que vous avez une table user
avec les colonnes name
et email
:
cursor.execute('select * from users')
results = get_results(cursor)
for res in results:
print(res.name, res.email)