2013-06-18 18 views
11

Ich versuche, Daten aus einem Wörterbuch in eine Datenbank mit benannten Parametern einzufügen. Ich arbeite mit einer einfachen SQL-Anweisung, z.Python Sqlite einfügen benannte Parameter oder Null

Fügt irgendwo in den Ort ein, 1000 in die Ankunftsspalte und 1001 in die Abfahrtsspalte.

Die Daten, die ich tatsächlich haben werde, enthalten Ort, aber kann entweder Ankunft oder Abreise enthalten, aber möglicherweise nicht beide (in diesem Fall entweder nichts oder NULL kann in die Tabelle gehen). In diesem Fall bekomme ich sqlite3.ProgrammingError: Sie haben keinen Wert liefern 2.

für die Bindung ich diese defaultdict unter Verwendung beheben können:

c.execute(SQL,defaultdict(str,dict)) 

Um die Dinge etwas komplizierter zu machen, werde ich tatsächlich haben eine Liste von Wörterbüchern, die mehrere Orte mit einer An- oder Abreise enthalten.

({'location': 'place1', 'departure': '1000'}, 
    {'location': 'palce2', 'arrival': '1010'}, 
    {'location': 'place2', 'departure': '1001'}) 

und ich möchte dies mit c.executemany laufen können, aber jetzt ich nicht defaultdict nutzen kann.

Ich könnte durch jedes Wörterbuch in der Liste durchlaufen und viele c.execute -Anweisungen ausführen, aber Executemany scheint ein aufgeräumter Weg, es zu tun.

Ich habe dieses Beispiel vereinfacht, die eigentlichen Daten haben viel mehr Einträge im Wörterbuch und ich baue es aus einer JSON-Textdatei.

Wer hat irgendwelche Vorschläge, wie ich das tun könnte?

Antwort

12

Verwenden None einfügen ein NULL:

dict = {'location': 'somewhere', 'arrival': '1000', 'departure': None} 

Sie ein Standardwörterbuch und einen Generator diese verwenden können, verwenden mit executemany():

defaults = {'location': '', 'arrival': None, 'departure': None} 

c.executemany(SQL, ({k: d.get(k, defaults[k]) for k in defaults} for d in your_list_of_dictionaries) 
+0

Dank Martin - das funktioniert. Für alle anderen Benutzer mit diesem Problem muss das Standardwörterbuch einen Eintrag für jedes mögliche Element enthalten, auch wenn das Wörterbuch immer vorhanden ist. Außerdem fehlt eine abschließende Klammer in der Executemany-Zeile. – user2497185

0

Es ist eine einfachere Lösung für dieses Problem, das sollte in den meisten Fällen machbar sein; passieren nurexecutemanyeine Liste vondefaultdictstatt einer Liste vondict.

Mit anderen Worten, wenn Sie von Grunde auf Ihre Zeilen als defaultdict bauen können Sie die Liste der defaultdict Zeilen direkt mit dem Befehl executemany, anstatt zu bauen sie als Wörterbücher passieren und später die Situation Patch executemany vor dem Gebrauch.

Das folgende Arbeitsbeispiel (Python 3.4.3) zeigt den Punkt:

import sqlite3 
from collections import defaultdict 
# initialization 
db = sqlite3.connect(':memory:') 
c = db.cursor() 
c.execute("CREATE TABLE status(location TEXT, arrival TEXT, departure TEXT)") 
SQL = "INSERT INTO status VALUES (:location, :arrival, :departure)" 
# build each row as a defaultdict 
f = lambda:None # use str if you prefer 
row1 = defaultdict(f,{'location':'place1', 'departure':'1000'}) 
row2 = defaultdict(f,{'location':'place2', 'arrival':'1010'}) 
rows = (row1, row2) 
# insert rows, executemany can be safely used without additional code 
c.executemany(SQL, rows) 
db.commit() 
# print result 
c.execute("SELECT * FROM status") 
print(list(zip(*c.description))[0]) 
for r in c.fetchall(): 
    print(r) 
db.close() 

Wenn Sie es ausführen, druckt es:

('location', 'arrival', 'departure') 
('place1', None, '1000') # None in Python maps to NULL in sqlite3 
('place2', '1010', None)