mysql工具和sql注入问题
Navicat软件
- 几乎所有的SQL语句,通过鼠标点点点的方式实现。
- 模型功能,表与表之间的关系很形象。
- 视图功能,SQL语句自动补全,局部执行功能很太实用
Pymysql模块
- pymysql模块是第三方模块,提供python连接并操作MySQL数据库的功能。通过pip下载。
- 通过
cursor对象执行sql语句查询和查询结果的显示。 cursor.excute()的返回结果是sql语句影响的条数cursor.fetchone\fetchmany\fetchall()获取查询结果cursor.scroll()回滚光标的位置。支持相对模式relative和绝对模式absolute- 其实,查询结果都保存在
_rows中(元组或列表),fetch和scroll只是修改在_rows中取值的索引
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456',
database='day48',
charset='utf8'
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 数据展现的格式,默认是元组的形式(仅有数据),此时指定为字典的形式,即可以看得见字段名和数据
sql = 'select * from student;'
res = cursor.execute(sql) # 返回受影响的条数
# print(cursor._rows) # 保存了所有的数据
print(cursor.fetchone()) # 取出一个数据
print(cursor.fetchmany(2)) # 取出多个数据
print(cursor.fetchall()) # 取数所有数据
cursor.scroll(-4, mode='relative')
print(cursor.fetchmany(2))
sql注入
利用sql语句注释或其他逻辑漏洞,书写一些特点的语句实现固定的语法。比如,对登录校验的sql注入
# --后面的内容注释了
select * from user where name='jason' -- jhsadklsajdkla' and password=''
# or 后面逻辑判断肯定为真
select * from user where name='xxx' or 1=1 -- sakjdkljakldjasl' and password=''
解决办法:敏感的数据不要自己拼接sql语句,交给execute帮你拼接即可。
# 比如登录校验
...
cursor = conn.cursor()
username = input('>>>:')
password = input('>>>:')
sql = "select * from user where name=%s and password=%s"
# 不要手动拼接数据 先用%s占位 之后将需要拼接的数据直接交给execute方法即可
rows = cursor.execute(sql, (username, password))
# 自动识别sql里面的%s用后面元组里面的数据替换
if rows:
print('登录成功')
print(cursor.fetchall())
else:
print('用户名密码错误')
补充
# execute 自动传参,占位符问题
def execute(self, query, args=None):
"""Execute a query
:param str query: Query to execute.
:param args: parameters used with query. (optional)
:type args: tuple, list or dict
:return: Number of affected rows
:rtype: int
If args is a list or tuple, %s can be used as a placeholder in the query.
If args is a dict, %(name)s can be used as a placeholder in the query.
"""
pymysql针对增删改的操作
-
pymysql针对数据的增删改的操作,需要二次确认操作,才可以真正的修改数据库。
sql = 'insert into student(gender, class_id, sname) values("男", 1, "哈哈")' effet_row = cursor.execute(sql) conn.commit() # 需要确认一次 -
如果嫌
conn.commit()麻烦,可以直接在实例化conn对象的时候,加一个参数autocommit=Trueconn = pymysql.connect( host='127.0.0.1', port=3306, user='root', passwd='123456', db='day48', charset='utf8', autocommit=True ) cursor = conn.cursor(pymysql.cursors.DictCursor) sql = 'insert into student(gender, class_id, sname)'values("男", 1, "哈哈")' effet_row = cursor.execute(sql) # 直接就修改数据库了 -
补充:如果批处理操作数据,可以使用
executemanycursor = conn.cursor(pymysql.cursors.DictCursor) sql = 'insert into student(gender, class_id, sname)values(%s, %s, %s)' item_list = [('男', 1, 's1'), ('男', 2, 's2'), ('女', 1, 's3'),] effet_row = cursor.executemany(sql, args=item_list) # 传一个列表 print(effet_row)
pymysql调用存储过程
- 通过接口
cursor.callproc(self, procname, args=()) - 可以通过
cursor.execute('select @_p1_2;')查看out类型的参数
import pymysql
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
passwd = '123456',
db = 'day48',
charset = 'utf8',
autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc('p1',(1,5,10))
"""
@_p1_0=1
@_p1_1=5
@_p1_2=10
"""
# print(cursor.fetchall())
cursor.execute('select @_p1_2;')
print(cursor.fetchall())
pymysql开启事务
- 异常捕获
- 回滚操作,
conn.rollback() - 没有因此常时,事务提交
conn.commit()
try:
cursor.execute(sql_1)
cursor.execute(sql_2)
cursor.execute(sql_3)
except Exception as e:
conn.rollback() # 事务回滚
print('事务处理失败', e)
else:
conn.commit() # 事务提交
print('事务处理成功', cursor.rowcount)# 关闭连接
cursor.close()
conn.close()

浙公网安备 33010602011771号