Python Sqlite3:INSERT INTO表VALUE(字典在这里)

时间:2013-01-01 05:55:25

标签: python dictionary parameters sqlite insert

我想使用字典将值插入表中,我该怎么做?

import sqlite3

db = sqlite3.connect('local.db')
cur = db.cursor()

cur.execute('DROP TABLE IF EXISTS Media')

cur.execute('''CREATE TABLE IF NOT EXISTS Media(
                id INTEGER PRIMARY KEY, title TEXT, 
                type TEXT,  genre TEXT,
                onchapter INTEGER,  chapters INTEGER,
                status TEXT
                )''')


values = {'title':'jack', 'type':None, 'genre':'Action', 'onchapter':None,'chapters':6,'status':'Ongoing'}

#What would I Replace x with to allow a 
#dictionary to connect to the values? 
cur.execute('INSERT INTO Media VALUES (NULL, x)'), values)
cur.execute('SELECT * FROM Media')

meida = cur.fetchone()

print meida

9 个答案:

答案 0 :(得分:26)

如果您尝试使用dict指定列名和值,则不能这样做,至少不能直接指定。

这在SQL中是非常固有的。如果您没有指定列名列表,则必须以CREATE TABLE顺序指定它们 - 这是dict无法做到的,因为dict没有订单。当然,如果您真的想要使用collections.OrderedDict,请确保它的顺序正确,然后传递values.values()。但在那时,为什么不首先只有list(或tuple)?如果你完全确定你已经按照正确的顺序获得了所有的价值,并且你想按顺序而不是按名称来引用它们,你所拥有的是list,而不是{{1} }。

并且无法在SQL中绑定列名(或表名等),只是值。

当然,您可以动态生成SQL语句。例如:

dict

然而,这几乎总是一个坏主意。这实际上并不比生成和columns = ', '.join(values.keys()) placeholders = ', '.join('?' * len(values)) sql = 'INSERT INTO Media ({}) VALUES ({})'.format(columns, placeholders) cur.execute(sql, values.values()) 动态Python代码好多少。而且你刚刚失去了使用占位符的所有好处 - 主要是防止SQL注入攻击,而且还有不太重要的事情,比如数据库引擎中更快的编译,更好的缓存等。

最好退一步从更高层次上看这个问题。例如,也许你真的不想要一个静态的属性列表,而是一个名称值exec表?或者,也许您想要某种基于文档的存储(无论是高性能的nosql系统,还是只存储在MediaProperties中的一堆JSON或YAML对象)?


使用named placeholders的替代方案:

shelve

答案 1 :(得分:10)

有一个使用词典的解决方案。首先是sql语句

INSERT INTO Media VALUES (NULL, 'x');

不起作用,因为它假定您按照CREATE TABLE语句中定义的顺序引用所有列,如abarnert所述。 (见SQLite INSERT。)

通过指定列修复它后,可以使用命名占位符来插入数据。这样做的好处是可以安全地转义关键字符,因此您不必担心。来自Python sqlite-documentation

values = {'title':'jack', 'type':None, 'genre':'Action', 'onchapter':None,'chapters':6,'status':'Ongoing'}
cur.execute('INSERT INTO Media (id, title, type, onchapter, chapters, status) VALUES (:id, :title, :type, :onchapter, :chapters, :status);'), values)

答案 2 :(得分:9)

您可以使用named parameters

cur.execute('INSERT INTO Media VALUES (NULL, :title, :type, :genre, :onchapter, :chapters, :status)', values)

这仍然取决于INSERT语句中的列顺序(那些:仅用作values dict中的键)但它至少不需要订购在python方面的值,加上你可以在values中有其他被忽略的东西;如果你把dict中的内容分开来将它存储在多个表中,这可能很有用。

如果您仍想避免重复名称,可以在执行虚拟查询后从sqlite3.Row结果对象或cur.description中提取它们;在CREATE TABLE的任何地方附近以python形式保持它们可能是更合理的。

答案 3 :(得分:1)

这是转义的一种更通用的方法:

# One way. If keys can be corrupted don't use.
sql = 'INSERT INTO demo ({}) VALUES ({})'.format(
            ','.join(my_dict.keys()),
            ','.join(['?']*len(my_dict)))

# Another, better way. Hardcoded w/ your keys.
sql = 'INSERT INTO demo ({}) VALUES ({})'.format(
            ','.join(my_keys),
            ','.join(['?']*len(my_dict)))

cur.execute(sql, tuple(my_dict.values()))

答案 4 :(得分:1)

2i + 2

查询变为

int current_index = 0;
node[] array = new node[2^n];
q nodes;
q.add(root);
while (!q.empty) {
   node current_node = q.front()
   array[current_index] = current_node;
   if (current_node.left != null)
      q.add(current_node.left);
   if (current_node.right != null)
      q.add(current_node.right);
   current_index++;
}

答案 5 :(得分:0)

key_lst = ('status', 'title', 'chapters', 'onchapter', 'genre', 'type')
cur.execute('INSERT INTO Media (status,title,chapters,onchapter,genre,type) VALUES ' + 
            '(?,?,?,?,?,?);)',tuple(values[k] for k in key_lst))

逃脱right

您可能还需要在某个地方进行commit来电。

答案 6 :(得分:0)

我遇到了类似的问题所以我首先创建了一个字符串,然后将该字符串传递给执行命令。它确实需要更长的时间来执行,但映射对我来说是完美的。只是一个解决方法:

create_string = "INSERT INTO datapath_rtg( Sr_no"
for key in record_tab:
    create_string = create_string+ " ," + str(key)
create_string = create_string+ ") VALUES("+ str(Sr_no) 
for key in record_tab:
    create_string = create_string+ " ," + str(record_tab[key])
create_string = create_string + ")"
cursor.execute(create_string)

通过做上述事情,我确保如果我的dict(record_tab)不包含特定字段,那么脚本不会抛出错误并且可以完成正确的映射,这就是我在第一时间使用字典的原因。

答案 7 :(得分:0)

我遇到了类似的问题并最终得到了一些与以下内容完全不同的东西(注意 - 这是OP的代码,其位数已经改变,因此它以他们请求的方式工作) -

import sqlite3
db = sqlite3.connect('local.db')
cur = db.cursor()

cur.execute('DROP TABLE IF EXISTS Media')

cur.execute('''CREATE TABLE IF NOT EXISTS Media(
                id INTEGER PRIMARY KEY, title TEXT, 
                type TEXT,  genre TEXT,
                onchapter INTEGER,  chapters INTEGER,
                status TEXT
                )''')


values = {'title':'jack', 'type':None, 'genre':'Action',     'onchapter':None,'chapters':6,'status':'Ongoing'}

#What would I Replace x with to allow a 
#dictionary to connect to the values? 
#cur.execute('INSERT INTO Media VALUES (NULL, x)'), values)
# Added code.
cur.execute('SELECT * FROM Media')
colnames = cur.description
list = [row[0] for row in cur.description]
new_list = [values[i] for i in list if i in values.keys()]
sql = "INSERT INTO Media VALUES ( NULL, "
qmarks = ', '.join('?' * len(values))
sql += qmarks + ")"
cur.execute(sql, new_list)
#db.commit() #<-Might be important.
cur.execute('SELECT * FROM Media')
media = cur.fetchone()
print (media)

答案 8 :(得分:0)

这太迟了,但是我想我会添加自己的答案。不是专家,但我发现有效果。

使用字典时存在保存顺序方面的问题,其他用户已经指出,但是您可以执行以下操作:

# We're going to use a list of dictionaries, since that's what I'm having to use in my problem
input_list = [{'a' : 1 , 'b' : 2 , 'c' : 3} , {'a' : 14 , 'b' : '' , 'c' : 43}]
for i in input_list:
    # I recommend putting this inside a function, this way if this 
    # Evaluates to None at the end of the loop, you can exit without doing an insert
    if i :
        input_dict = i 
    else:
        input_dict = None
        continue
# I am noting here that in my case, I know all columns will exist.
# If you're not sure, you'll have to get all possible columns first.

keylist = list(input_dict.keys())
vallist = list(input_dict.values())

query = 'INSERT INTO example (' +','.join( ['[' + i + ']' for i in keylist]) + ') VALUES (' + ','.join(['?' for i in vallist]) + ')'

items_to_insert = list(tuple(x.get(i , '') for i in keylist) for x in input_list)
# Making sure to preserve insert order. 

conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.executemany(query , items_to_insert)
conn.commit()