
现在有一个需要 在程序中使用不定长的字典构造 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 |