18

名前付きパラメーターを使用して、辞書からデータベースにデータを挿入しようとしています。私はこれを単純なSQLステートメントで動作させています。

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: You did not supply a value for binding 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 テキスト ファイルから作成しています。

これを行う方法について何か提案はありますか?

4

2 に答える 2

18

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)
于 2013-06-18T13:12:33.857 に答える
1

この問題には、ほとんどの場合に実行可能な、より簡単な解決策があります。のリストの代わりに のリストに渡すだけ です。executemany defaultdict dict

言い換えれば、行を辞書として構築し、後で使用する前に状況にパッチを当てる代わりに、行のリストをコマンドに直接defaultdict渡すことができるため、行を最初から構築する場合。defaultdictexecutemanyexecutemany

次の作業例 (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)
于 2015-08-21T00:05:33.877 に答える