前言
本文主要试图使用占位符或其他方法来动态更新字段,达到对多个字段进行批量更新。但是在摸索一段时间后仍没能解决,倒是了解了sql防注入的风险。
我们知道,pymysql批量更新是使用executemany(sql,data)。 当想对多个字段进行批量更新,自然而然想到用这样的形式。
data = [['字段1',123,'admin'],['字段2',234,'admin']]
sql = 'update user_table set %s=%s where username =%s'
cur.executemany(sql,data)
这样写报错。
mysql中的字段是用 ` (tab键上方的引号)括起来的。用占位符传值这种形式,会自动带上单引号',且pymysql 的占位符并不是 python 的通用占位符。
如果是只需要传值,那么这里的sql是正常的。但如果是表名和key,sql会变成这样:
sql="update "table" set "key"="value"
解决办法:
一、对于批量更新语句
暂时没有找到可以使用 executemany(sql,data) 进行批量更新的办法。
1- 提前将sql语句拼接好。
sql="update" + table + " set " + key + "=%s" # 注意set前后的空格
cursor.execute(sql, (value,))
# cursor.execute(sql, value)
2- 使用%s作为字段占位符,带(参数)传值,有sql注入风险
# 对表名和字段使用了%s占位符,此种写法成功执行了sql语句。
sql = 'update %s set %s="%s"' %(表名,字段名,值)
cursor.execute(sql)
# 以下几种对表名和字段使用了%s占位符,在执行sql语句时均报错
# updata = [['字段1','字段1值','用户名'],['字段12','字段2值','用户名']]
# sql = 'update user_table set %s=%s where username =%s'
# cur.executemany(sql,updata)
# cur.execute(sql,updata[0])
# cur.execute(sql,(col_id,cnt,username)) #col_id = '字段1', cnt = '字段1值'
conn.commit()
3- 防sql注入
a、字典传值
#1- 使用字典传值,不能传表名和字段名
# 以下对字段名进行传值,报错
# sql = 'update user_table set %(col_id)s=%(cnt)s where username =%(name)s'
# data = {'col_id':'counts','cnt':cnt,'name':username}
# cur.execute(sql,data)
# conn.commit()
sql = 'update user_table set counts =%(cnt)s where username =%(name)s'
data = {'cnt':cnt,'name':username}
cur.execute(sql,data)
conn.commit()
b、,逗号传值,不要用%
sql = "insert into 表名 (字段名1,字段名2,字段名3,) values (%s,%s,%s)"
cur.execute(sql, (val1,val2,val3))
# sql = "insert into 表名 (字段名1,字段名2,字段名3,) values (%s,%s,%s)" %(val1,val2,val3)
# cur.execute(sql) # 有sql注入风险
4- {}.format形式作为表名或字段名占位
二、对于批量插入语句
用逗号连接将字段列表转成字符串
field_names = ','.join(field_names)