2010-07-21 148 views
71
db = sqlite.connect("test.sqlite") 
res = db.execute("select * from table") 

通過迭代,我得到了與這些行相關的列表。如何從sqlite查詢獲得字典?

for row in res: 
    print row 

我可以列

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

的名字,但有一些功能或設置爲獲取字典而不是列表?

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

還是我必須自己做?

+0

的可能重複[Python的 - MySQLdb的,SQLite的結果作爲字典(HTTP:// stackoverflow.com/questions/4147707/python-mysqldb-sqlite-result-as-dictionary) – vy32 2015-08-22 22:50:09

+1

@ vy32:這個問題是從2010年7月,你鏈接到2010年11月。所以,這是一個愚蠢的。正如人們所期望的那樣,反向評論已經被提上了那個:-) – aneroid 2016-06-07 20:49:16

回答

109

你可以在示例中的文檔使用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"] 

或同樣遵循此例中的文檔之後給出的建議是:

如果返回一個元組沒有按」 t足夠 並且您希望基於名稱訪問 列,則應考慮將row_factory設置爲 sqlite3.Row類型。行同時提供 基於索引和不區分大小寫的 基於名稱的訪問列與 幾乎沒有內存開銷。它可能會比你自己的 基於自定義字典的方法或 更好,即使是基於db_row的解決方案。

+49

只需引用文檔,'con.row_factory = sqlite3.Row' – 2010-12-30 01:19:30

+0

如果列名中包含特殊字符例如'SELECT 1 AS'dog [cat]「'那麼'cursor'將不會有正確的描述來創建一個字典。 – Crazometer 2016-06-16 06:23:49

+0

我已經設置了'connection.row_factory = sqlite3.Row',我嘗試了'connection.row_factory = dict_factory'如圖所示,但'cur.fetchall()'仍然給我一個元組列表 - 任何想法爲什麼這不起作用? – displayname 2016-12-07 10:51:45

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. 

所以,是的,自己做。

+0

>在數據庫之間有所不同 - 比如說,sqlite 3.7和3.8? – Nucular 2014-03-07 17:23:18

+0

@ user1123466:...像SQLite,MySQL,Postgres,Oracle,MS SQL Server,Firebird ... – 2014-03-07 17:52:41

15

即使使用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))  
+6

sqlite3.Row實現了映射協議。你可以做'print'%(id)i - %(name)s:%(value)s「%dict(row)' – Mzzzzzz 2015-06-11 14:07:28

0

或者您可以將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 
0

一個普通的選擇,只用三行

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

我想我回答,即使答案是亞當Schmideg的和Alex馬爾泰利的答案部分提到了這個問題。爲了讓像我這樣有相同問題的人能夠輕鬆找到答案。

conn = sqlite3.connect(":memory:") 
conn.row_factory = sqlite3.Row#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) 
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

較短的版本:

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

這對我很好。謝謝! – 2017-12-19 20:22:52

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

結果肯定是真的,但我不知道最好。

1

在我的測試中最快:

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) 

VS:

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) 

你決定:)