使用python操作mysql的逻辑如下图所示。基本过程为:1、开始;2、创建连接connection;3、创建并获取操作游标cursor;4、执行操作;5、关闭游标cursor;6、关闭连接; 7、结束。下面我们举一个简单例子s1python_mysql_sample.py 来实现向goods_cates表里插入两行数据:(0,'硬盘'),(0,'光盘')。
import pymysql # 1、导入pymsql模块
# connect对象用于建立连接
# host:mysql主机
# port: mysql端口默认3306
# database:数据库名称
# user: 用户名
# password: 密码
# charset: 通信编码
# 2、创建连接,设置连接ip,port,用户,密码,以及所要连接的数据库
conn = pymysql.connect(host='localhost', port=3306,database='jing_dong', user='root', password='hitzzy',
charset='utf8')
# cursor对象用于执行SQL语句
# 3、创建游标, 操作数据库, 指定游标返回内容为字典类型
cs1 = conn.cursor()
# 4、执行语句 execute(),返回受影响的行数结果。
count = cs1.execute('insert into goods_cates(name) values("硬盘")')
print(count)
count = cs1.execute('insert into goods_cates(name) values("光盘")')
print(count)
# 5、提交操作
conn.commit()
# 6、关闭游标和连接
cs1.close()
conn.close()
运行程序后,通过mysql终端查询语句查询goods_cates表,我们会发现,末尾已经添加了两行我们刚才添加的数据。
** (注意SQL注入)**
'''sql注入'''
import pymysql
def main():
find_name = input('请输入物品名称:') # 输入想要查询的物品名称
# print('select * from goods where name like %{}%' .format(find_name))
# 创建连接
conn = pymysql.connect(host='localhost', port=3306,database='jing_dong', user='root', password='hitzzy',
charset='utf8')
# 获取游标
cs1 = conn.cursor()
# 执行select语句,并返回受影响的行数:查询所有数据
# 安全模式
count = cs1.execute('select * from goods where name=%s', [find_name])
# 非安全模式
# 当find_name 被输入 " or 1 or " 包含双引号时,会显示表中所有数据,造成数据泄露。
# sql = 'select * from goods WHERE name="%s"' % find_name
# count = cs1.execute(sql)
print('查询到%d条数据:' % count)
# 获取并打印查询到的数据
for i in range(count):
# fetchone()执行查询语句时获取被影响的行的第一行
result = cs1.fetchone() # result 为一个元组哦
# print(type(result)) # 可以查看result的数据类型,加深理解
print(result)
# 关闭游标和连接
cs1.close()
conn.close()
if __name__ == '__main__':
main()
可以看到,当输入 x240 超极本,查询到此商品在库,并打印出该结果。
不要着急,我们把代码中安全模式的行注释掉,将非安全模式的行取消注释,然后再次输入 x240 超极本。我们也能查询到该商品信息。也就是说,execute里可以是一个SQL语句的字符串。那为什么还需要前面语法介绍的参数赋值呢?
再查询一种商品(“ or 1 or ”),再看看结果。奇怪,goods表中所有的数据都显示出来了。为什么呢?我们来分析一下。当把(“ or 1 or ”)赋值给find_name时,sql字符串变量的值为 select * from goods where name="“ or 1 or ”";大家看一下,where后的语句结果始终为True。所以会显示出goods表中所有数据,造成数据库数据泄露。因此在使用execute语句时,尽量使用安全模式中的参数化赋值,以避免因疏忽造成的SQL注入并引发安全问题。
sql注入中最常见的就是字符串拼接,研发人员对字符串拼接应该引起重视,不应忽略。
错误用法1:
sql= "select id, name from test where id=%d and name='%s'" %(id, name)
cursor.execute(sql)
错误用法2:
sql= "select id, name from test where id="+ str(id) +"and name='"+ name +"'"cursor.execute(sql)
正确用法1:
args=(id, name)
sql= "select id, name from test where id=%s and name=%s"cursor.execute(sql, args)
execute()函数本身有接受sql语句参数位的,可以通过python自身的函数处理sql注入问题。
正确用法2:
name=MySQLdb.escape_string(name)
sql= "select id, name from test where id=%d and name='%s'" %(id, name)
cursor.execute(sql)
python模块MySQLdb自带针对mysql的字符转义函数escape_string,可以对字符串转义。