param
换成 tuple :(param,)
或者换成list : [param]
with DBHelper as db:
pid = 10010
db.fetch_tuple_as_list("SELECT `name` FROM `vien_table` WHERE `id` = %s LIMIT 1", pid)
with DBHelper as db:
names = [(a),(b),(c)]
db.update_batch("INSERT INTO vien_table
(name
) VALUES(%s)", names)
- DBHelper的两个方法fetch_tuple_as_list、update_batch:
def fetch_dict_as_list(self, sql, params = None): if not self._dcursor: self._dcursor = self.get_cursor(MySQLdb.cursors.DictCursor) try: self._dcursor.execute(sql, params) self._current_cursor = self._dcursor res = self._dcursor.fetchall() if res: return list(res) except Exception as e: print self.get_time(),'Unable to get results !',e return None
def update_batch(self,sql,items,stepsize = 1000): if not self._tcursor: self._tcursor = self.get_cursor() try: size = int(stepsize) length = len(items) size = size if length >= size else length print size for i in xrange(0, (length + size - 1) / size): self._tcursor.executemany(sql,items[isize:(i+1)size]) self._current_cursor = self._tcursor if self._autocommit: self._conn.commit() return True except Exception as e: if self._autocommit: self._conn.rollback() print self.get_time(),'Unable to update !\n',e return False
> 可以看到,其实最后我调用的是MySQLdb的execute和executemany方法。而错误的位置就在这里,参数转换的时候没有执行成功。
MySQLdb/cursors.py line 187: query = query % tuple([db.literal(item) for item in args])
> 上述是源码,可以看到这里其实就是将所有传入参数遍历,然后对每一个item用literal处理,literal函数其实就是对item进行转义,然后在加上引号作为字符串以便MySQL识别。例如`str = "low's" , sql = ' SELECT * FROM table where name = %s ' % str` 这种情况下最后的sql是`SELECT * FROM table where name = low's ` 这样就会给MySQL造成困惑,而不能执行,最简单的方法就是给%s加上引号,像这样`"%s"` ,然后给str转义,像这样 `low\'s`。这样我们交给MySQL的就是`SELECT * FROM table where name = "low\'s"'`。而其实literal就是做了这样一件事,它会把low's变成'low\\\'s',之所以是 `\\` 是因为它先转`\` 然后交给MySQL的就是low\'s了,正好满足需求。
> 言归正传,由于execute是把你传入的参数当成一个Iterator来遍历了,如果你只是传入一个简单的参数,就会造成convert失败,所以如何解决呢?可能你现在就可以想到了,那我传入一个tuple。没错,这个是可以的,但是你会不会直接这样用呢`execute(sql,('vien'))`,如果是这样那你就错了,可以试一下输出`type(('vien'))`,你会发现结果不是`tuple`而是`string`!Python官方文档是这样解释的:如果tuple只有一个值,那么不会被当做是tuple,而是这个值的类型。所以你要用tuple怎么用呢,很简单,加个逗号:`('vien',)` 这样就会被当成是tuple了,当然你也可以将它变成list,list就简单多了,直接`['vien']` 就好了。所以我给这个DBHelper加了个方法,来处理这种情况:
def format_param(self,param,batch = False): if param: if batch: return [i if (isinstance(i,tuple) or isinstance(i,list)) else [i] for i in param] (isinstance(param,tuple) or isinstance(param,list)) and param or [param] return None
> 这样问题就解决了。
viencoding.com版权所有,允许转载,但转载请注明出处和原文链接: https://viencoding.com/article/60