2013-06-18 90 views
11

我想從字典插入數據到數據庫使用命名參數。我有一個簡單的SQL語句,例如python sqlite插入命名參數或null

SQL = "INSERT INTO status (location, arrival, departure) VALUES (:location, :arrival,:departure)" 
dict = {'location': 'somewhere', 'arrival': '1000', 'departure': '1001'} 
c.execute(SQL,dict) 

將某處插入位置,將1000插入到達列中,將1001插入到離開列中。

我實際擁有的數據將包含位置,但可能包含到達或離開,但可能不包含兩者(在這種情況下,無論是空還是NULL都可以進入表格)。在這種情況下,我得到sqlite3.ProgrammingError:您沒有爲綁定2.

提供一個值,我可以通過使用defaultdict解決這個問題:

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

爲了讓事情變得複雜一些,我實際上將有包含到達或離開多個地點的字典列表。

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

我想用c.executemany運行這個,但是我現在不能使用defaultdict。

我可以遍歷列表中的每個字典並運行許多c.execute語句,但executemany似乎是一種更加簡單的方法。

爲了方便起見,我簡化了這個例子,實際的數據在字典中有更多的條目,我從JSON文本文件構建它。

任何人有任何建議,我怎麼能做到這一點?

回答

12

使用None插入NULL

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

您可以使用默認字典和發電機與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

感謝馬丁 - 工程。對於任何有此問題的人,即使實際的字典總是擁有它,默認字典也需要包含每個可能項的條目。此外,executemany行上還有一個缺失的最後關閉括號。 – user2497185

0

有一個簡單的解決這個問題應該在大多數情況下是可行的; 只是傳遞給executemanydefaultdict,而不是dict列表清單。

換句話說,如果你從頭開始建立自己的行作爲defaultdict可以的defaultdict排列表中直接傳遞到命令executemany,而不是建立他們的字典和使用executemany前後來修補的情況。

下面的工作示例(Python 3.4.3)表明了這一點:

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

如果你運行它,它打印:

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