5月11日 python学习总结 子查询、pymysql模块增删改查、防止sql注入问题
一、子查询
子查询:把一个查询语句用括号括起来,当做另外一条查询语句的条件去用,称为子查询
select emp.name from emp inner join dep on emp.dep_id = dep.id where dep.name="技术";
select name from emp where dep_id =
(select id from dep where name="技术");
查询平均年龄在25岁以上的部门名
select name from dep where id in
(select dep_id from emp group by dep_id having avg(age) > 25);
select dep.name from emp inner join dep on emp.dep_id = dep.id
group by dep.name
having avg(age) > 25;
查看不足2人的部门名(子查询得到的是有人的部门id)
补:exists存在
select * from emp where exists (
select id from dep where id > 3
);
查询每个部门最新入职的那位员工
select t1.id,t1.name,t1.post,t1.hire_date,t2.post,t2.max_date from emp as t1 inner join
(select post,max(hire_date) as max_date from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date
;
二、pymysql模块
基本操作之查询:
import pymysql #pip3 install pymysql conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db42', charset='utf8' ) cursor=conn.cursor(pymysql.cursors.DictCursor) #查询结果以字典形式显示 sql='select * from class;' rows=cursor.execute(sql) #执行一条sql语句,返回值是执行结果的行数 print(rows) print(cursor.fetchone()) #取出一行执行结果,光标向后移动一位 print(cursor.fetchone()) #取出第二行执行结果 光标向后移动一位 print(cursor.fetchmany(2)) #取出两行执行结果 光标向后移动两位 print(cursor.fetchall()) #取出剩余的全部 print(cursor.fetchall()) # print(cursor.fetchall()) # cursor.scroll(3,'absolute') # 绝对路径 光标从最开始的位置开始向后移动3个位置 # print(cursor.fetchone()) #取出当前光标所在位置的数据,并将光标后移 print(cursor.fetchone()) print(cursor.fetchone()) cursor.scroll(1,'relative') #相对路径 光标从当前位置开始向后移动3个位置 print(cursor.fetchone()) conn.commint() #提交事务 cursor.close() conn.close()
基本操作之增改:
import pymysql #pip3 install pymysql conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db42', charset='utf8' ) cursor=conn.cursor(pymysql.cursors.DictCursor) #一次插入一行记录 sql='insert into user(username,password) values(%s,%s)' rows=cursor.execute(sql,('EGON','123456')) print(rows) print(cursor.lastrowid) rows=cursor.execute('update user set username="alexSB" where id=2') print(rows) # 一次插入多行记录 sql='insert into user(username,password) values(%s,%s)' rows=cursor.executemany(sql,[('lwz','123'),('evia','455'),('lsd','333')]) print(rows) print(cursor.lastrowid) conn.commit() # 只有commit提交才会完成真正的修改 cursor.close() conn.close()
三、防止sql注入问题
1、当输入 正确的用户名 并在其后加上 '--' sql注释符时, 我们执行这条sql 后边的密码验证判断就被注释掉了,从而没有密码就可以登录
2、 或者 在用户输入用户名时,随意输入用户名 并加上 'or 1=1' 这种语句,则跳过了账户密码的验证直接登陆进去了
所以rows=cursor.execute(sql)这种拼接sql ,直接执行的方法并不可靠
import pymysql #pip3 install pymysql conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', database='db42', charset='utf8' ) cursor=conn.cursor(pymysql.cursors.DictCursor) inp_user=input('用户名>>:').strip() #inp_user="" inp_pwd=input('密码>>:').strip() #inp_pwd="" sql="select * from user where username='%s' and password='%s'" %(inp_user,inp_pwd) #1、当输入 正确的用户名 并在其后加上 '--' sql注释符时, 我们执行这条sql 后边的密码验证判断就被注释掉了,从而没有密码就可以登录 #2、 或者 在用户输入用户名时,随意输入用户名 并加上 'or 1=1' 这种语句,则跳过了账户密码的验证直接登陆进去了 rows=cursor.execute(sql) #所以这种拼接sql ,直接执行的方法并不可靠 if rows: print('登录成功') else: print('登录失败') cursor.close() conn.close()
解决办法:
pymysql 为我们提供了过滤字符串中特殊符号的功能
使用如下方法传入参数,会自动帮我们过滤掉特殊字符,防止sql注入
inp_user=input('用户名>>:').strip() #inp_user="" inp_pwd=input('密码>>:').strip() #inp_pwd="" sql="select * from user where username=%s and password=%s" rows=cursor.execute(sql,(inp_user,inp_pwd))