我在python中有一本字典。它们的键是具有不同大小的元组,包含unicode字符,值只是一个int数。我想将这个字典插入带有2列表的sqlite数据库中。
第一列用于键值,第二列应具有相应的int值。我为什么要这样做?好吧,我有一个非常大的字典,我使用cPickle,甚至将协议设置为2.大小仍然很大,保存和加载此文件需要很多时间。所以我决定把它保存在db中。该字典仅在程序开头加载一次到内存中,因此没有额外的操作。
现在的问题是我想将元组完全保存为元组(而不是字符串),所以每当我将表加载到内存中时,我都可以立即构建我的字典而没有任何问题。 有谁知道我怎么能这样做?
答案 0 :(得分:3)
有几件事。首先,SQLite不允许您直接存储Python数据结构。其次,我猜你想要能够根据需要通过元组键查询值,所以你不想腌制和取消选择,然后搜索字典中的键。
问题是,你不能用元组查询,你不能将元组条目分成它们自己的列,因为它们的大小各不相同。如果必须使用SQLite,则几乎必须连接元组中的unicode字符,可能使用的分隔符不是元组值中的1个字符。将其用作键,并将其存储在SQLite中作为主键列的列中。
def tuple2key(t, delimiter=u':'):
return delimiter.join(t)
import sqlite3
conn = sqlite3.connect('/path/to/your/db')
cur = conn.cursor()
cur.execute('''create table tab (k text primary key, value integer)''')
# store the dict into a table
for k, v in my_dict.iteritems():
cur.execute('''insert into tab values (?, ?)''', (tuple2key(k), v))
cur.commit()
# query the values
v = cur.execute(''' select value from tab where key = ? ''', tuple2key((u'a',u'b'))).fetchone()
答案 1 :(得分:2)
可以将元组存储到sqlite db中并在元组上创建索引。它需要一些额外的代码来完成它。 在这种特殊情况下将元组存储到db中是否是一个合适的解决方案是另一个问题(可能是一个双键解决方案更适合)。
import sqlite3
import pickle
def adapt_tuple(tuple):
return pickle.dumps(tuple)
sqlite3.register_adapter(tuple, adapt_tuple) #cannot use pickle.dumps directly because of inadequate argument signature
sqlite3.register_converter("tuple", pickle.loads)
def collate_tuple(string1, string2):
return cmp(pickle.loads(string1), pickle.loads(string2))
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
con.create_collation("cmptuple", collate_tuple)
cur = con.cursor()
cur.execute("create table test(p tuple unique collate cmptuple) ")
cur.execute("create index tuple_collated_index on test(p collate cmptuple)")
#insert
p = (1,2,3)
p1 = (1,2)
cur.execute("insert into test(p) values (?)", (p,))
cur.execute("insert into test(p) values (?)", (p1,))
#ordered select
cur.execute("select p from test order by p collate cmptuple")
答案 2 :(得分:-1)
我认为最好在表中创建3列 - key1,key2和value。
如果您希望将密钥保存为元组,您仍然可以使用pickle但仅适用于密钥。然后你可以把它保存为blob。
>>> pickle.dumps((u"\u20AC",u"\u20AC"))
'(V\\u20ac\np0\ng0\ntp1\n.'
>>> pickle.loads(_)
(u'\u20ac', u'\u20ac')
>>>