Python MySQLDB:在列表中获取 fetchall 的结果

Posted

技术标签:

【中文标题】Python MySQLDB:在列表中获取 fetchall 的结果【英文标题】:Python MySQLDB: Get the result of fetchall in a list 【发布时间】:2012-10-03 17:53:42 【问题描述】:

我想在列表中而不是元组的元组或字典的元组中获取 fetchall 操作的结果。 例如,

cursor = connection.cursor() #Cursor could be a normal cursor or dict cursor
query = "Select id from bs"
cursor.execute(query)
row = cursor.fetchall()

现在,问题是结果行是 ((123,),(234,)) 或 ('id':123, 'id':234) 我正在寻找的是 (123,234) 或 [123,234]。如果我可以节省解析结果集,那就最好了。提前致谢

【问题讨论】:

可能必须提供一个自定义 Cursor 类来执行此操作。 django db 后端执行此操作,因此您可以在那里寻找灵感。例如,django.db.backends.mysql.base.CursorWrapper 用于 MySQL 游标之上,但我不确定它在哪里注册。这可能意味着提供一个自定义数据库后端来返回您的自定义光标。在访问时解析所需的数据可能会更容易。 【参考方案1】:
list= [list[0] for list in cursor.fetchall()]

这会将结果呈现在一个列表中,例如 - list = [122,45,55,44...]

【讨论】:

【参考方案2】:

以这种方式制作你的光标对象:

db = MySQLdb.connect("IP", "user", "password", "dbname")

cursor = db.cursor(MySQLdb.cursors.DictCursor)

然后当你对查询执行 cursor.fetchall() 时,将获得一个字典元组,你可以稍后将其转换为列表。

data = cursor.fetchall()

data = list(data)

【讨论】:

【参考方案3】:

在搜索扁平化数据库查询时,Google 上出现了这个旧 Q,所以这里有更多建议...

考虑一个快速的list-flattening iterator。

其他答案使用fetchall(),它首先将所有行加载到内存中,然后对其进行迭代以创建一个新列表。可能效率低下。可以结合MySQL所谓的server side cursor:

# assume mysql on localhost with db test and table bs
import itertools
import MySQLdb
import MySQLdb.cursors

conn = MySQLdb.connect(host='localhost',db='test', 
          cursorclass=MySQLdb.cursors.SSCursor ) 
cursor = conn.cursor()
# insert a bunch of rows
cursor.executemany('INSERT INTO bs (id) VALUES (%s)',zip(range(1,10000)) )
conn.commit()
# retrieve and listify
cursor.execute("select id from bs")
list_of_ids = list(itertools.chain.from_iterable(cursor))
len(list_of_ids)
#9999
conn.close()

但问题也被标记为Django,它有一个很好的single field query flattener

class Bs(models.Model):
    id_field = models.IntegerField()

list_of_ids = Bs.objects.values_list('id_field', flat=True)

【讨论】:

晚了几年,但这是 OP 所要求的 - 由于他的数据点数量,创建一个列表而不使用 fetch all()。【参考方案4】:

我相信,经过这么长时间,你已经解决了这个问题,但是,对于一些可能不知道如何使用 MySQLdb 将游标的值作为字典获取的人,你可以使用找到的这个方法@ 987654321@:

import MySQLdb as mdb

con = mdb.connect('localhost', 'testuser', 'test623', 'testdb')

with con:

    cur = con.cursor(mdb.cursors.DictCursor)
    cur.execute("SELECT * FROM Writers LIMIT 4")

    rows = cur.fetchall()

    for row in rows:
        print row["Id"], row["Name"]

【讨论】:

我在尝试获取属性时出现错误tuple indices must be integers or slices, not str【参考方案5】:
cursor.execute("""Select * From bs WHERE (id = %s)""",(id))

cursor.fetchall()

【讨论】:

【参考方案6】:

如果只有一个字段,我可以使用它从数据库中创建一个列表:

def getFieldAsList():
    kursor.execute("Select id from bs")
    id_data = kursor.fetchall()
    id_list = []
    for index in range(len(id_data)):
        id_list.append(id_data[index][0])
    return id_list

【讨论】:

【参考方案7】:

那么列表推导呢?如果结果是((123,), (234,), (345,)):

>>> row = [item[0] for item in cursor.fetchall()]
>>> row
[123, 234, 345]

如果结果是('id': 123, 'id': 234, 'id': 345):

>>> row = [item['id'] for item in cursor.fetchall()]
>>> row
[123, 234, 345]

【讨论】:

如果这个场景只是一个例子,你打算如何处理具有多个字段的查询?这就是为什么你首先得到一个元组的元组 谁说的例子?我只想获取一列 id,行数以百万计。我想对数据进行后处理,这就是为什么我试图找出一种方法来避免这种昂贵的操作。 @RaunakAgarwal - 请保持文明 - 您没有在问题中提及您所面临的限制,因此有人建议展开嵌套客户端是完全合理的。您应该提到您正在处理数百万行。 @RaunakAgarwal 也许您可以使用生成器而不是列表推导。我想它不会那么贵,因为生成器有惰性评估 @César:是的,这可能是一回事。但是生成器只会帮助我控制我想要加载的项目数量,这些项目可以从光标本身实现。可能,我必须在数据库级别本身进行计算。不过还是谢谢。

以上是关于Python MySQLDB:在列表中获取 fetchall 的结果的主要内容,如果未能解决你的问题,请参考以下文章

带有 MySQLdb 的 Python Tkinter 列表框

在 python 中使用 MySQLdb 插入 mysql 后,如何安全有效地获取行 ID?

在 python 中使用 MySQLdb 插入 mysql 后,如何安全有效地获取行 ID?

如何使用python mysqldb一次插入多行

Python MySQLdb/mysqlclient:绑定命名集(或元组或列表)作为参数

蟒蛇:MYSQLdb。如何在不执行 select * 在大表中获取列名?