现在有一个需要 在程序中使用不定长的字典构造 sql 语句 Insert INTO (字典的键) VALUE (字典的值) 由于使用于 mysql,因为安全原因,不想使用+法来构造 其他三种 python 字符串构造方法好像都不行, a.使用% b.使用 format() c.使用 f-string 我没想出来方案,请大神指点迷津
1
todd7zhang 2020-03-27 17:15:10 +08:00
d = {'name': 123, 'age': 456}
keys = d.keys() sql = 'insert into (%s) value (%s)' % (','.join('%s' % k for k in keys), ','.join('%%s' for _ in keys)) cr.execute(sql, tuple(d.values())) |
2
todd7zhang 2020-03-27 17:15:56 +08:00
后面是 %s for_ in keys
关键是 构造出 'insert into (name, age) values (%s, %s)' 就行了 |
3
Vegetable 2020-03-27 17:26:11 +08:00
我寻思这加号和直接字符串方法在安全上有区别吗?不都是直接拼接 SQL 吗?
|
4
wuwukai007 2020-03-27 17:26:38 +08:00 via Android
没看懂+怎么会不安全,用了多线程吗
|
5
sikong31 2020-03-27 17:26:40 +08:00
def insert(self, table, **kw):
fields, values = zip(*kw.items()) fields_str = ','.join(fields) values_str = ','.join(['?'] * len(fields)) sql = f"INSERT INTO {table} ({fields_str}) values ({values_str})" self.con.execute(sql, values) |
6
wysnylc 2020-03-27 17:27:40 +08:00
注入警告
|
7
xpresslink 2020-03-27 17:32:26 +08:00
>>> d = {'name': 123, 'age': 456}
>>> 'insert into table{0} values{1};'.format(tuple(d.keys()),tuple(d.values())) "insert into table('name', 'age') values(123, 456);" >>> |
8
xpresslink 2020-03-27 17:37:44 +08:00
但是不建议一条一条的插入,最好用批量插入,数据量大了效率差万倍。
建一个插入模板 >> sql = 'insert into (name, age) values (%s, %s)' >> conn.executemany(sql, list(d.values())) 大多数 python 的 mysql 驱动接口都带 executemany()方法。 |
9
sikong31 2020-03-27 17:39:11 +08:00
@xpresslink 他这是不定长的字典,键多少不固定,批量不了
|
10
ClericPy 2020-03-27 18:05:44 +08:00
防注入就用框架吧... 我现在用的 databases, 貌似是基于 aiomysql 和 sqlalchemy 的, 直接丢字典进去就行了...
|
11
fzhyzamt 2020-03-27 18:21:53 +08:00
mysql 那几个库好像自带防注入的,只要你不把数据直接 format 到语句里,所以你提的那三种方式没啥区别
|
12
j0shfan OP @todd7zhang 这样可行,感谢方案
|
13
j0shfan OP @xpresslink 可以,简洁明了
|
15
j0shfan OP @xpresslink 感谢提醒
|
16
Trim21 2020-03-27 19:30:40 +08:00
|