2011-02-15 37 views
38

我不是在要求SHOW COLUMNS命令。MySQL:從查詢中獲取列名或別名

我想創建一個與heidisql類似的應用程序,您可以在其中指定SQL查詢,並在執行時返回包含表示查詢結果的行和列的結果集。結果集中的列名應與SQL查詢中定義的所選列匹配。

在我的Python程序中(使用MySQLdb)我的查詢只返回行和列結果,但不返回列名。在以下示例中,列名將是ext,totalsizefilecount。 SQL最終將從程序中外部化。

我能想出這個工作的唯一方法是編寫我自己的SQL解析器邏輯來提取選定的列名。

有沒有簡單的方法來獲取所提供的SQL的列名? 接下來我需要知道查詢返回多少列?

# 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

謝謝Daniel DiPaulo ......這就是我正在尋找的答案。我只寫了我自己的SQL解析器,以便可以提取選擇列名稱/別名。工作正常。 – panofish 2011-02-16 20:38:02

+0

感謝user625477 ...這是更好的答案。爲什麼沒有stackoverflow發送電子郵件給我更新的答案? – panofish 2013-04-25 14:01:09

回答

153

cursor.description會給你一個元組的元組,其中每個元素的[0]是列標題。

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

爲什麼這個答案不正確?這顯然是OP所需要的。 – thefreeman 2012-12-25 05:05:08

+0

我從來沒有收到更新答案的電子郵件。 – panofish 2013-04-25 13:57:14

5

我認爲這應該做你所需要的(建立在上面的答案上)。我相信這是一種更加pythony的方式來寫它,但你應該得到的總體思路。

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

這是一樣的thefreeman但使用列表和字典解析

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

pprint.pprint(result) 
9

類似@詹姆斯的回答更Python的方式,更Python的方式可以是:

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

你可以通過地圖得到一列結果:

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

或篩選結果:

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

或累積值過濾列:

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

你也可以使用MySQLdb.cursors.DictCursor。這將您的結果集轉換爲python字典的python列表,儘管它使用了特殊的光標,因此在技術上比可接受的答案便攜性更低。不知道速度。這是使用此編輯的原始代碼。

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

標準詞典功能應用,例如,len(row[0])數列數第一行,list(row[0])列名的列表(第一行),等等。希望這有助於!