wake-up-neo.net

Wie kann ich Diktate aus der SQLite-Abfrage erhalten?

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

Mit Iteration bekomme ich Listen, die den Zeilen entsprechen.

for row in res:
    print row

Ich kann den Namen der Spalten erhalten

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

Gibt es eine Funktion oder Einstellung, um Wörterbücher anstelle von Listen zu erhalten?

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

oder muss ich mich selber machen

85
Meloun

Sie können row_factory wie im Beispiel in den Dokumenten verwenden:

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

oder folgen Sie den Anweisungen, die direkt nach diesem Beispiel in den Dokumenten gegeben werden:

Wenn die Rückgabe eines Tuples nicht ausreicht und Sie möchten einen namenbasierten Zugriff auf Spalten sollten Sie die Einstellung .__ in Betracht ziehen. row_factory zum hochoptimierten Typ sqlite3.Row. Row liefert beides indexbasiert und unabhängig von Groß- und Kleinschreibung Namensbasierter Zugriff auf Spalten mit fast kein Speicheraufwand. Es wird wahrscheinlich besser als deine eigene Benutzerdefinierte Wörterbuch-basierte Vorgehensweise oder sogar eine auf db_row basierende Lösung.

127
Alex Martelli

Selbst wenn Sie die Klasse sqlite3.Row verwenden, können Sie die String-Formatierung immer noch nicht in folgender Form verwenden:

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

Um dies zu umgehen, verwende ich eine Hilfsfunktion, die die Zeile übernimmt und in ein Wörterbuch konvertiert. Ich verwende dies nur, wenn das Wörterbuchobjekt dem Row-Objekt vorzuziehen ist (z. B. für Formatierungen, bei denen das Row-Objekt die Dictionary-API nicht auch nativ unterstützt). Verwenden Sie das Row-Objekt jedoch zu allen anderen Zeiten. 

def dict_from_row(row):
    return dict(Zip(row.keys(), row))       
18
bbengfort

Ich dachte, ich beantworte diese Frage, auch wenn die Antwort in den Antworten von Adam Schmideg und Alex Martelli teilweise erwähnt wird. Damit andere wie ich die gleiche Frage haben, können sie die Antwort leicht finden.

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
15
gandalf

Von 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.

Also ja, mach es selbst.

Kürzere Version:

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

Am schnellsten bei meinen Tests:

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)

Du entscheidest :)

2
Ran Aroussi

Nach dem Herstellen einer Verbindung zu SQLite: con = sqlite3.connect(.....) reicht es aus, nur Folgendes auszuführen:

con.row_factory = sqlite3.Row

Voila!

1

Ähnlich wie die zuvor genannten Lösungen, aber am kompaktesten:

db.row_factory = lambda C, R: { c[0]: R[i] for i, c in enumerate(C.description) }
0
Falko
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)

Das Ergebnis ist definitiv wahr, aber ich weiß nicht das Beste.

0
Emrah Tuncel

Wörterbücher in Python bieten willkürlichen Zugriff auf ihre Elemente . Jedes Wörterbuch mit "Namen", obwohl es einerseits informativ sein kann (dh wie die Feldnamen sind), "entreißt" die Felder, was unerwünscht sein kann.

Am besten ist es, die Namen in einer separaten Liste zusammenzufassen und sie bei Bedarf selbst mit den Ergebnissen zu kombinieren.

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

Denken Sie auch daran, dass die Namen in allen Ansätzen die Namen sind, die Sie in der Abfrage angegeben haben, nicht die Namen in der Datenbank. Ausnahme ist der SELECT * FROM

Wenn Sie nur die Ergebnisse mit einem Wörterbuch abrufen möchten, verwenden Sie auf jeden Fall den conn.row_factory = sqlite3.Row (bereits in einer anderen Antwort angegeben).

0
ilias iliadis

Oder Sie können die sqlite3.Rows wie folgt in ein Wörterbuch konvertieren. Dies gibt ein Wörterbuch mit einer Liste für jede Zeile.

    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
andere

Eine generische Alternative mit nur drei Zeilen

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

Wenn Ihre Abfrage jedoch nichts zurückgibt, führt dies zu einem Fehler. In diesem Fall...

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

oder

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