我如何从 sqlite 查询中获取字典?

2025-03-18 08:55:00
admin
原创
47
摘要:问题描述:db = sqlite.connect("test.sqlite") res = db.execute("select * from table") 通过迭代,我得到了与行对应的列表。for row in res: print row 我可以得到列的名...

问题描述:

db = sqlite.connect("test.sqlite")
res = db.execute("select * from table")

通过迭代,我得到了与行对应的列表。

for row in res:
    print row

我可以得到列的名称

col_name_list = [tuple[0] for tuple in res.description]

但是是否有一些函数或设置可以获取字典而不是列表?

{'col1': 'value', 'col2': 'value'}

还是我必须自己做?


解决方案 1:

您可以使用row_factory,如文档中的示例所示:

import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]

或者按照文档中此示例后面给出的建议进行操作:

如果返回元组还不够,并且您希望基于名称访问列,则应考虑将 row_factory 设置为高度优化的 sqlite3.Row 类型。Row 提供基于索引和不区分大小写的基于名称的列访问,几乎没有内存开销。它可能比您自己的自定义字典方法甚至基于 db_row 的解决方案更好。

以下是第二种解决方案的代码:

con = sqlite3.connect(…)
con.row_factory = sqlite3.Row   #   add this row
cursor = con.cursor()

解决方案 2:

尽管 Adam Schmideg 和 Alex Martelli 的回答都部分提到了这个问题,但我还是想回答这个问题。为了让其他和我一样有同样问题的人轻松找到答案。

conn = sqlite3.connect(":memory:")

#This is the important part, here we are setting row_factory property of
#connection object to sqlite3.Row(sqlite3.Row is an implementation of
#row_factory)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from stocks')

result = c.fetchall()
#returns a list of dictionaries, each item in list(each dictionary)
#represents a row of the table

解决方案 3:

连接到 SQLite 后,
con = sqlite3.connect(.....)只需运行:

con.row_factory = sqlite3.Row

瞧!

解决方案 4:

即使使用 sqlite3.Row 类——您仍然不能使用以下形式的字符串格式:

print "%(id)i - %(name)s: %(value)s" % row

为了解决这个问题,我使用了一个辅助函数,该函数接受行并将其转换为字典。我只在字典对象比 Row 对象更可取时才使用它(例如,对于字符串格式化,Row 对象本身不支持字典 API)。但其他时候都使用 Row 对象。

def dict_from_row(row):
    return dict(zip(row.keys(), row))       

解决方案 5:

正如@gandalf的回答所述,必须使用conn.row_factory = sqlite3.Row,但结果不是直接的字典。必须dict在最后一个循环中添加一个额外的“转换”:

import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute('create table t (a text, b text, c text)')
conn.execute('insert into t values ("aaa", "bbb", "ccc")')
conn.execute('insert into t values ("AAA", "BBB", "CCC")')
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from t')
for r in c.fetchall():
    print(dict(r))

# {'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
# {'a': 'AAA', 'b': 'BBB', 'c': 'CCC'}

解决方案 6:

来自PEP 249:

Question: 

   How can I construct a dictionary out of the tuples returned by
   .fetch*():

Answer:

   There are several existing tools available which provide
   helpers for this task. Most of them use the approach of using
   the column names defined in the cursor attribute .description
   as basis for the keys in the row dictionary.

   Note that the reason for not extending the DB API specification
   to also support dictionary return values for the .fetch*()
   methods is that this approach has several drawbacks:

   * Some databases don't support case-sensitive column names or
     auto-convert them to all lowercase or all uppercase
     characters.

   * Columns in the result set which are generated by the query
     (e.g.  using SQL functions) don't map to table column names
     and databases usually generate names for these columns in a
     very database specific way.

   As a result, accessing the columns through dictionary keys
   varies between databases and makes writing portable code
   impossible.

是的,自己动手吧。

解决方案 7:

我测试过的最快:

conn.row_factory = lambda c, r: dict(zip([col[0] for col in c.description], r))
c = conn.cursor()

%timeit c.execute('SELECT * FROM table').fetchall()
19.8 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

与:

conn.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])
c = conn.cursor()

%timeit c.execute('SELECT * FROM table').fetchall()
19.4 µs ± 75.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

你决定:)

解决方案 8:

简短版本:

db.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])

解决方案 9:

与前面提到的解决方案类似,但更紧凑:

db.row_factory = lambda C, R: { c[0]: R[i] for i, c in enumerate(C.description) }

解决方案 10:

获取查询结果

output_obj = con.execute(query)
results = output_obj.fetchall()

选项 1) 使用 Zip 的显式循环

for row in results:
    col_names = [tup[0] for tup in output_obj.description]
    row_values = [i for i in row]
    row_as_dict = dict(zip(col_names,row_values))

选项 2)使用 Dict Comp 实现更快的循环

for row in results:
    row_as_dict = {output_obj.description[i][0]:row[i] for i in range(len(row))}

解决方案 11:

我认为你走在正确的轨道上。让我们保持非常简单并完成你想要做的事情:

import sqlite3
db = sqlite3.connect("test.sqlite3")
cur = db.cursor()
res = cur.execute("select * from table").fetchall()
data = dict(zip([c[0] for c in cur.description], res[0]))

print(data)

缺点是.fetchall(),如果您的表非常大,这会严重消耗您的内存。但对于仅处理几千行文本和数字列的简单应用程序来说,这种简单的方法已经足够了。

对于严肃的事情,你应该研究排工厂,正如许多其他答案所建议的那样。

解决方案 12:

或者你可以将 sqlite3.Rows 转换为字典,如下所示。这将给出一个字典,其中包含每行的列表。

    def from_sqlite_Row_to_dict(list_with_rows):
    ''' Turn a list with sqlite3.Row objects into a dictionary'''
    d ={} # the dictionary to be filled with the row data and to be returned

    for i, row in enumerate(list_with_rows): # iterate throw the sqlite3.Row objects            
        l = [] # for each Row use a separate list
        for col in range(0, len(row)): # copy over the row date (ie. column data) to a list
            l.append(row[col])
        d[i] = l # add the list to the dictionary   
    return d

解决方案 13:

通用替代方案,仅使用三行

def select_column_and_value(db, sql, parameters=()):
    execute = db.execute(sql, parameters)
    fetch = execute.fetchone()
    return {k[0]: v for k, v in list(zip(execute.description, fetch))}

con = sqlite3.connect('/mydatabase.db')
c = con.cursor()
print(select_column_and_value(c, 'SELECT * FROM things WHERE id=?', (id,)))

但如果您的查询没有返回任何内容,则会导致错误。在这种情况下...

def select_column_and_value(self, sql, parameters=()):
    execute = self.execute(sql, parameters)
    fetch = execute.fetchone()

    if fetch is None:
        return {k[0]: None for k in execute.description}

    return {k[0]: v for k, v in list(zip(execute.description, fetch))}

或者

def select_column_and_value(self, sql, parameters=()):
    execute = self.execute(sql, parameters)
    fetch = execute.fetchone()

    if fetch is None:
        return {}

    return {k[0]: v for k, v in list(zip(execute.description, fetch))}

解决方案 14:

import sqlite3

db = sqlite3.connect('mydatabase.db')
cursor = db.execute('SELECT * FROM students ORDER BY CREATE_AT')
studentList = cursor.fetchall()

columnNames = list(map(lambda x: x[0], cursor.description)) #students table column names list
studentsAssoc = {} #Assoc format is dictionary similarly


#THIS IS ASSOC PROCESS
for lineNumber, student in enumerate(studentList):
    studentsAssoc[lineNumber] = {}

    for columnNumber, value in enumerate(student):
        studentsAssoc[lineNumber][columnNames[columnNumber]] = value


print(studentsAssoc)

结果肯定是正确的,但我不知道最好的结果是什么。

解决方案 15:

Python 中的字典提供对其元素的任意访问。因此,任何带有“名称”的字典,尽管一方面可能提供信息(即字段名称是什么),但会“取消对字段的排序”,这可能是不受欢迎的。

最好的方法是将名称放在单独的列表中,然后根据需要自行将其与结果相结合。

try:
         mycursor = self.memconn.cursor()
         mycursor.execute('''SELECT * FROM maintbl;''')
         #first get the names, because they will be lost after retrieval of rows
         names = list(map(lambda x: x[0], mycursor.description))
         manyrows = mycursor.fetchall()

         return manyrows, names

还要记住,在所有方法中,名称都是您在查询中提供的名称,而不是数据库中的名称。例外情况是SELECT * FROM

如果您唯一关心的是使用字典获取结果,那么绝对使用conn.row_factory = sqlite3.Row(已在另一个答案中说明)。

解决方案 16:

def getUsers(self,assoc=False):
        result = self.cursor.execute("SELECT * FROM users").fetchall()
        result_len = len(result)
        if(result_len == False): return
        if(assoc != True):
            return result
        else:
            result_formated = []
            columns = [column[0] for column in self.cursor.description]
            for row in result:
                row_dict = {}
                i = 0
                # print(result_len)
                while(i <= result_len):
                    row_dict[columns[i]] = row[i]
                    i += 1
                result_formated.append(row_dict)
            return result_formated

我就把我的错误代码留在这里

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用