MySQL:从查询中获取列名或别名


72

我不是要SHOW COLUMNS命令。

我想创建一个与heidisql相似的应用程序,您可以在其中指定SQL查询,并在执行时返回包含代表查询结果的行和列的结果集。结果集中的列名称应与您在SQL查询中定义的所选列匹配。

在我的Python程序中(使用MySQLdb),我的查询仅返回行和列的结果,但不返回列名。在下面的例子中,列名应为exttotalsizefilecount。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()      

cursor.column_names
Amin,

Answers:


233

cursor.description将为您提供一个元组元组,其中每个[0]是列标题。

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

6
cursor.column_names也这样做
Amin

1
在MySQLdb 1.2.5cursor.column_names中缺少。
Yaroslav Nikitenko

30

这与thefreeman相同,但更多的是使用列表和字典理解的pythonic方式

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

pprint.pprint(result)

15

与@James答案类似,更Python化的方式可以是:

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

您可以在结果上获得带有map的单列:

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

彻底。使用fetchall而不是在游标上进行迭代有好处吗?
cs_alumnus

@kzarns:我想说的是简化示例,并获得完整列表。您可以创建一个生成器函数,而不是使用来遍历光标yield,并且可以使用更少的内存。
juandesant 2014年

对我不起作用,仅转换第一行,稍作调整即可使其工作:fields = [i[0] for i in cursor.description] 然后 result = [dict(zip(fields,row)) for row in cursor.fetchall()]行之有效
pdem

10

我认为这应该做您所需要的(基于以上答案)。我敢肯定,还有一种更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)

1
还有没有其他简单的方法,为什么它不使用字段返回值?
Surya prakash Patel

6

您也可以使用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])名列表(第一行)等。希望这对您有所帮助!


很好,但是我正在写一个实用程序,查询会发生变化,我需要在查询中支持字段顺序。字典光标对字段没有排序。
panofish


3

这只是已接受答案的附加组件:

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

在哪里dotdict

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

这将使您可以更轻松地按列名访问值。
假设您有一个user包含列name和的表email

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


1

尝试:

cursor.column_names

mysql连接器版本:

mysql.connector.__version__
'2.2.9'

1

您也可以这样做以获取字段标题:

table = cursor.description
check = 0
for fields in table:
    for name in fields:
        if check < 1:
            print(name),
        check +=1
    check =0

非常好的主意,谢谢!我真的想通过查询来获取列,您的建议提供了一种不错的方式<cursor>.execute('describe <table>')然后取回
Cryo

0

与建议的解决方案相似,只有结果是json with column_header : vaulefor db_queryie sql

cur = conn.cursor()
cur.execute(sql)
res = [dict((cur.description[i][0], value) for i, value in enumerate(row)) for row in cur.fetchall()]

输出json示例:

[
   {
      "FIRST_ROW":"Test 11",
      "SECOND_ROW":"Test 12",
      "THIRD_ROW":"Test 13"
   },
   {
      "FIRST_ROW":"Test 21",
      "SECOND_ROW":"Test 22",
      "THIRD_ROW":"Test 23"
   }
]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.