Python Sqlite3:插入到表值中(字典在这里)

Python Sqlite3:插入到表值中(字典在这里),python,dictionary,parameters,sqlite,insert,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, ty

我想使用字典在表中插入值,我该如何做

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

如果您试图使用
dict
来指定列名和值,那么您不能这样做,至少不能直接这样做

这是SQL的固有特性。如果不指定列名列表,则必须按
CREATE TABLE
顺序指定列名,这是
dict
无法执行的,因为
dict
没有顺序。当然,如果您真的想这样做,可以使用
collections.OrderedDict
,确保其顺序正确,然后只需传递
values.values()
。但是在这一点上,为什么不首先创建一个
列表
(或者
元组
)呢?如果您完全确定已按正确的顺序获得所有值,并且希望按顺序而不是按名称引用它们,那么您拥有的是一个
列表,而不是
dict

在SQL中没有办法绑定列名(或表名等),只能绑定值

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

columns = ', '.join(values.keys())
placeholders = ', '.join('?' * len(values))
sql = 'INSERT INTO Media ({}) VALUES ({})'.format(columns, placeholders)
values = [int(x) if isinstance(x, bool) else x for x in values.values()]
cur.execute(sql, values)
然而,这几乎总是一个坏主意。这实际上并不比生成和执行动态Python代码好多少。首先,您已经失去了使用占位符的所有好处——主要是防止SQL注入攻击,但也失去了一些不太重要的东西,如更快的编译、更好的缓存等

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


另一种方法是使用:

做好逃生准备


您可能还需要在某个地方调用
commit

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

INSERT INTO Media VALUES (NULL, 'x');
不起作用,因为它假设您引用的是所有列,按照abarnert所述的
CREATE TABLE
语句中定义的顺序。(见附件。)

一旦通过指定列修复了它,就可以使用命名占位符插入数据。这样做的好处是可以安全地转义关键字符,因此您不必担心。从:

您可以使用:

这仍然取决于
INSERT
语句中的列顺序(那些
仅用作
dict中的键),但它至少不必在python端对值进行排序,另外,您可以在
中忽略其他内容;如果您将dict中的内容分开存储在多个表中,这可能会很有用


如果仍然希望避免重复名称,可以在执行虚拟查询后,从
sqlite3.Row
结果对象或从
cur.description
提取名称;在您执行
创建表

的任何位置附近,以python形式保存它们可能更明智,因为我遇到了类似的问题,所以我首先创建了一个字符串,然后将该字符串传递给执行命令。执行确实需要更长的时间,但映射对我来说是完美的。只是一个变通办法:

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)不包含特定字段,那么脚本不会抛出错误,并且可以进行正确的映射,这就是我最初使用dictionary的原因。

我遇到了类似的问题,并最终得到了与以下内容并不完全不同的结果(注意-这是OP的代码,更改了位,以使其按照要求的方式工作)-

导入sqlite3 db=sqlite3.connect('local.db') cur=db.cursor() cur.execute('DROP TABLE IF executes Media') 当前执行(“”)如果媒体不存在,则创建表( id整数主键,标题文本, 键入文本,类型文本, 一章整数,一章整数, 状态文本 )''') 值={'title':'jack','type':无,'genre':'Action','onchapter':无,'chapters':6,'status':'consuming'} #我将用什么替换x以允许 #连接到值的字典? #当前执行('INSERT INTO Media VALUES(NULL,x)')、值) #添加了代码。 当前执行('SELECT*FROM Media') colnames=cur.description 列表=[当前描述中的行的行[0] new_list=[values[i]如果i在values.keys()中,则列表中i的值[i] sql=“插入媒体值(空,” qmarks=',join('?'*len(值)) sql+=qmarks+“”” 当前执行(sql,新列表)
#db.commit()#这里有一种更通用的方法,它有转义的好处:

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

这已经太晚了,但我想我会加上我自己的答案。不是专家,但我发现有些东西是有效的

在使用字典时保留顺序会出现问题,其他用户已经说明了这一点,但您可以执行以下操作:

# 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()
查询变成

insert into table_name ('id', 'name', 'address') values(123, 'Abc', 'xyz');

这里的问题是:你为什么要这样做?你想实现什么?为什么你认为保持两个完全不同的指定内容(SQL表和
dict
键集)同步是正确的方法?不知道原始作者想要什么,但我发现了这个问题,因为我正在从XML文件的结构生成
create table
,然后,当我转到插入行时,我在dict中有属性和VAL,我知道db会有它们,但它们从来都不是静态的。@eichin我知道这有点晚了,但是。。。如果您只是从XML预加载数据库,以便以后更静态地使用,我可能会构建一个加载脚本,而不是一堆插入;如果您实际上一直在使用动态列访问数据库,那么应该认真考虑
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)
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)
# 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()))
# 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()
dictionary = {'id':123, 'name': 'Abc', 'address':'xyz'}    
query = "insert into table_name " + str(tuple(dictionary.keys())) + " values" + str(tuple(dictionary.values())) + ";"
cursor.execute(query)
insert into table_name ('id', 'name', 'address') values(123, 'Abc', 'xyz');