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

问题描述 投票:0回答:13

我不是在要求

SHOW COLUMNS
命令。

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

在我的 Python 程序中(使用

MySQLdb
),我的查询仅返回行和列结果,但不返回列名称。在以下示例中,列名称为
ext
totalsize
filecount
。 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()      
python mysql mysql-python
13个回答
288
投票

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

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

46
投票

这与 thefreeman 的答案相同,但使用列表和字典理解以更 Pythonic 的方式

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

pprint.pprint(result)

34
投票

与@James的回答类似,更Pythonic的方式可以是:

fields = [field_md[0] for field_md in cursor.description]
result = [dict(zip(fields,row)) for row in cursor.fetchall()]

您可以获得对结果进行列表理解的单列:

extensions = [row['ext'] for row in result)

或在列表理解中使用附加的 if 来过滤结果:

large = [row for row in result if row['filesize'] > 1024 and row['filesize'] < 4096]

或累积过滤列的值:

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

14
投票

我认为这应该可以满足您的需要(基于上面的答案)。我确信有一种更 Python 的方式来编写它,但你应该了解总体思路。

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)

9
投票

您也可以使用

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])
计算列名称列表(第一行)等。希望这有帮助!


9
投票

这只是已接受答案的附加内容:

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)

5
投票

与建议的解决方案类似,只是结果是 json,其中

column_header : vaule
表示
db_query
,即
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"
   }
]

3
投票

尝试:

cursor.column_names

mysql 连接器版本:

mysql.connector.__version__
'2.2.9'

2
投票

看起来 MySQLdb 实际上并没有提供该 API 调用的翻译。相关的 C API 调用是

mysql_fetch_fields
,并且 没有对应的 MySQLdb 翻译


1
投票

您也可以执行此操作来获取字段标题:

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

1
投票

cursor.column_names
是一个很好又简单的。


-1
投票

列名=光标.字段名


-1
投票

找到了一种使用

pymysql
pandas

拥有像 sql 这样的列的简单方法
import pymysql
import pandas as pd

db  = pymysql.connect(host="myhost", user="myuser", passwd="mypass", db="mydb")

query  = """SELECT ext
              SUM(size) as totalsize,
              COUNT(*) as filecount
            FROM fileindex
            GROUP BY ext 
            ORDER BY totalsize DESC;
         """
df = pd.read_sql_query(query,db)

DataFrame 默认情况下将具有列名称 ext、totalsize、filecount,无需执行其他操作。

以我为例:

© www.soinside.com 2019 - 2024. All rights reserved.