我有一个大型SQLite数据库,其中包含大量文本和许多其他列var1
... var 50
。其中大多数是数字的,但有些是基于文本的。
我正在尝试从数据库中提取数据,在python中处理它并将其写回来 - 我需要对数据库中的所有行执行此操作。
到目前为止,以下类型的作品:
# get row using select and process
fields = (','.join(keys)) # "var1, var2, var3 ... var50"
results = ','.join([results[key] for key in keys]) # "value for var1, ... value for var50"
cur.execute('INSERT OR REPLACE INTO results (id, %s) VALUES (%s, %s);' %(fields, id, results))
但是,这会使我没有显式添加的列为空。我可以通过重新编写代码来解决这个问题,但是这感觉非常混乱,因为我必须使用字符串连接和重写数据来包围引号(即我没有更改的列)。
显然,在行上运行更新的方法是这样的:
update table set var1 = 4, var2 = 5, var3="some text" where id = 666;
据推测,我的方式是运行map
,并以某种方式添加=
标志(不确定如何),但我如何恰当地引用所有结果(因为我必须引用文本字段,它们也可能包含引号..)?
我有点困惑。任何指针都会非常有用。
谢谢!
答案 0 :(得分:3)
正如其他人所强调的那样,使用参数化参数。下面是一个示例,说明如何在具有可变数量的键时构造SQL语句:
sql=('UPDATE results SET '
+ ', '.join(key+' = ?' for key in keys)
+ 'WHERE id = ?')
args = [results[key] for key in keys] + [id]
cur.execute(sql,args)
答案 1 :(得分:1)
使用参数substitution。它比字符串格式更强大(我认为更安全)。
所以,如果你做了像
这样的事情query = 'UPDATE TABLE SET ' + ', '.join(str(f) + '=?,' for f in fields) + ';'
或者
query = 'UPDATE TABLE SET %s;' % (', '.join(str(f) + '=?,' for f in fields))
或使用新样式格式:
query = 'UPDATE TABLE SET {0};'.format(', '.join(str(f) + '=?,' for f in fields))
所以完整的程序看起来像这样:
vals = {'var1': 'foo', 'var2': 3, 'var24':999}
fields = vals.keys()
results = vals.values()
query = 'UPDATE TABLE SET {0};'.format(', '.join(str(f) + '=?,' for f in fields))
conn.execute(query, results)
这应该有效 - 我认为你应该做你想做的事。
答案 2 :(得分:0)
你不必关心报价等事情,事实上你不应该这样。如果你这样做,它不仅更方便,而且还处理称为sql注入的安全问题:
sql = "update table set var1=%s, var2=%s, var3=%s where id=666"
cursor.execute(sql, (4, 5, "some text"))
这里的关键点是sql和第二个语句中的值没有用“%”分隔,而是用“,” - 这不是字符串操作,而是你将两个参数传递给执行函数,实际的sql和值。每个%s由值元组中的值替换。然后数据库驱动程序知道如何处理各种类型的值。
insert语句可以用同样的方式重写,虽然我不确定并且目前无法测试你是否也可以用这种方式替换字段名(insert-sql语句中的第一个%s)
所以回到你的整体问题,你可以循环你的值并为你的第i个变量动态添加“,var%d = %% s”%i,同时将实际值添加到同一个列表中时间