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

Với tính lặp lại, tôi nhận được các danh sách từ bỏ các hàng.Làm cách nào để có được dict từ truy vấn sqlite?

for row in res: 
    print row 

Tôi có thể lấy tên của các cột

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

Nhưng có một số chức năng hoặc thiết lập để có được từ điển thay vì danh sách?

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

hoặc tôi phải tự làm?

+0

thể trùng lặp của [Python - mysqlDB, kết quả sqlite như từ điển] (http: // stackoverflow.com/questions/4147707/python-mysqldb-sqlite-result-as-dictionary) – vy32

+1

@ vy32: Câu hỏi này là từ tháng 7 năm 2010, câu hỏi bạn đã liên kết là tháng 11 năm 2010. Vậy đó là bản dupe. Và như người ta mong đợi, bình luận ngược lại đã được đưa vào đó :-) – aneroid

Trả lời

109

Bạn có thể sử dụng row_factory, như trong ví dụ trong tài liệu:

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"] 

hoặc làm theo những lời khuyên đó là trao ngay sau khi ví dụ này trong các tài liệu:

Nếu trả về một tuple doesn' t suffice và bạn muốn truy cập dựa trên tên vào các cột , bạn nên xem xét đặt row_factory thành tối ưu hóa cao sqlite3.Loại này. Hàng cung cấp cả hai quyền truy cập dựa trên chỉ mục và phân biệt chữ hoa chữ thường và không phân biệt dạng chữ theo chỉ mục cho các cột có hầu như không có phí trên bộ nhớ. Nó sẽ có thể tốt hơn cách tiếp cận dựa trên từ điển tùy chỉnh của riêng bạn hoặc ngay cả một giải pháp dựa trên db_row.

+49

Chỉ cần trích dẫn tài liệu, 'con.row_factory = sqlite3.Row' –

+0

Nếu tên cột của bạn có các ký tự đặc biệt trong ví dụ như "SELECT 1 AS" dog [cat] "' ​​thì con trỏ 'sẽ không có mô tả chính xác để tạo ra một dict. – Crazometer

+0

Tôi đã đặt 'connection.row_factory = sqlite3.Row' và tôi đã thử' connection.row_factory = dict_factory' như được hiển thị nhưng 'cur.fetchall()' vẫn cho tôi một danh sách các bộ dữ liệu - bất kỳ ý tưởng nào tại sao nó không hoạt động ? – displayname

6

Từ 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. 

Vì vậy, có, tự mình làm.

+0

> khác nhau giữa các cơ sở dữ liệu - như thế nào, sqlite 3.7 và 3.8? – Nucular

+0

@ user1123466: ... Giống như giữa SQLite, MySQL, Postgres, Oracle, MS SQL Server, Firebird ... –

15

Thậm chí sử dụng sqlite3.Row class-- bạn vẫn không thể sử dụng chuỗi định dạng trong các hình thức:

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

Để vượt qua điều này, tôi sử dụng một hàm helper mà mất hàng và chuyển đổi sang một từ điển. Tôi chỉ sử dụng điều này khi đối tượng từ điển thích hợp hơn với đối tượng Row (ví dụ: đối với những thứ như định dạng chuỗi trong đó đối tượng Row không hỗ trợ cả API từ điển). Nhưng sử dụng đối tượng Row tất cả các lần khác.

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

sqlite3.Row thực hiện giao thức ánh xạ. Bạn chỉ có thể làm 'in '% (id) i -% (tên) s:% (giá trị) s"% dict (hàng) ' – Mzzzzzz

0

Hoặc bạn có thể chuyển đổi sqlite3.Rows sang từ điển như sau. Điều này sẽ cung cấp cho một từ điển với một danh sách cho mỗi hàng.

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

Một thay thế chung, chỉ sử dụng ba dòng

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

Nhưng nếu truy vấn của bạn trả về không có gì, sẽ gây ra lỗi. Trong trường hợp này...

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

hoặc

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

Tôi nghĩ tôi trả lời câu hỏi này mặc dù câu trả lời là một phần đề cập trong cả hai câu trả lời Adam Schmideg và Alex Martelli của. để những người khác như tôi có cùng câu hỏi, để tìm câu trả lời dễ dàng.

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

phiên bản ngắn hơn:

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

Điều này làm việc tuyệt vời cho tôi. Cảm ơn! –

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) 

Kết quả là chắc chắn đúng, nhưng tôi không biết là tốt nhất.

1

nhanh nhất các bài kiểm tra của tôi:

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) 

Bạn quyết định :)

Các vấn đề liên quan