我有一个问题,也许它在某处得到了解答,但我找不到答案。 所以我得到了一个包含一个表的Sqlite数据库,比如手机型号和制造商:
Samsung
Apple
Iphone
Apple
Galaxy
Samsung
Ipod
Nexus
所以我想要实现的是使脚本替换:
Iphone or Ipod -> Apple
Galaxy or Nexus -> Samsung
我想有一个像字典这样的数据结构(我知道这个例子是不可能的,但仅用于说明)我可以从文件中读取以进行UPDATE查询:
{
'Apple':'Iphone','Ipod'
'Samsung':'Galaxy','Nexus'}
所以当脚本找到任何值时,它会用键替换它
值可能相当多 - 比如大约10,所以使用if /或语句将是不切实际的,我不是每次我都需要改变一些东西去代码并纠正它 - 所以这就是为什么我要保留我的“字典“在文本文件中并从脚本中读取。
对于任何指向正确方向的想法,我将不胜感激
谢谢。
答案 0 :(得分:1)
首先,您可以创建一个将替换值映射到“原始值”列表的字典:
replacements = {
'Apple':['Iphone','Ipod'],
'Samsung':['Galaxy','Nexus']
}
你可以把它放到像mapping.py这样的文件中,然后做from mapping import replacements
。 JSON也是一种合理的序列化格式。获得字典后,您可以遍历所有字段,生成符合要替换的字符串长度的参数化查询。
for replacement, replacables in replacements.iteritems():
query = 'update foo set value=? where value in ({})'.format(",".join("?"*len(replacables)))
c.execute(query, [replacement]+replacables)
这样您就不会进行SQL注入。当我尝试时,它最多可以处理100个变量,而不是1000个。我还没有检查它到底有多远。
答案 1 :(得分:0)
注意:以下不再安全的SQL注入!
之前的数据库:
$ sqlite3 foo.db .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t (f varchar);
INSERT INTO "t" VALUES('foo');
INSERT INTO "t" VALUES('bar');
INSERT INTO "t" VALUES('baz');
COMMIT;
映射的JSON文件:
{"B": ["bar", "baz"], "F": ["foo"]}
Python代码:
import json
import sqlite3
d = json.loads("d.json")
con = sqlite3.connect("foo.db")
cur = con.cursor()
# Loop over the keys in d.
for k in d:
# Build the SQL clause that matches all recordss for d[k].
clause = " or ".join(" f = '{}' ".format(v) for v in d[k])
# The SQL for the update.
sql = "update t set f = '{}' where {}".format(k, clause)
cur.execute(sql)
con.commit()
数据库之后:
$ sqlite3 foo.db .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t (f varchar);
INSERT INTO "t" VALUES('F');
INSERT INTO "t" VALUES('B');
INSERT INTO "t" VALUES('B');
COMMIT;
答案 2 :(得分:0)
如果您必须一次性进行大量替换,我建议使用带有新旧列的临时表
所以你的字典看起来像
Iphone,Apple
ipad公司,苹果
的Nexus,三星
银河,三星
您可以使用批量加载程序将此词典上传到临时表
然后运行单个更新命令一次更新所有旧值
Oracle中SQL的要点是
update yourtable
set yourtable.phone = (select temp.new
from yourtable , temp
where
temp.old = yourtable.phone)
where exists
(
select 1 from yourtable , temp
where
temp.old = yourtable.phone
)