5.7
昨日回顾
-
单表查询,查询主要关键字
select distinct 字段1,字段2 from 表名 where 分组之前的筛选条件 group by 分组条件 having 分组之后的筛选条件 order by 排序字段1 asc, 排序字段2 desc limit 5,5 # 一次显示的数据量
-
where
where id>= 3 and id<=6 where id between 3 and 6 where salary=18000 or salary=17000 where salary not in (1800,17000) # 模糊匹配 % 任意多个字符 _ 任意当个字符 where name like '____'; # 限制查询四个字符的名字 where char_length(name) = 4; # 判断null的时候,用is,不用=null where post_comment is null;
-
group by
# 分组的应用场景非常的广泛:每个,平均,最大,最小。。。 # 分组之后只能获取到分组的依据,其他字段都无法直接获取 select post from emp group by post; # 想要在分组后拿到其他数据,使用group_concat:获取分组之外的字段信息,拼接多个字段 select post,group_concat(salary,':',name) from emp; # concat:分组之前帮我们获取字段信息并且拼接成多个字段 select concat(name,'??') from emp; # conncat_ws:如果多个字段连接的符号是相同的情况下,可以使用concat_ws连接 select concat_ws(':',name,age,sex) from emp; # as 语法 # 1. 可以给展示字段起别名 # 2. 可以给表其别名 # 聚合函数:聚合函数必须在分组之后使用 max,min,sum,count,avg
-
having
# 分组之后再进行筛选操作,用法跟where一样,跟在group by后面
-
distinct
# 去重 # 数据必须是一模一样,才能去重 select distinct post from emp; # 不能带主键
-
order by
# 排序,默认是升序asc # order by salary; == order by salary asc, order by salary desc; order by salary asc, age desc; # 支持多个字段排序
-
limit
# 限制显示数据的展示条数 select * from emp limit 5; # 展示5条数据 limit 5,5 # 从第5条开始,展示5条
-
正则
# 正则是一门独立的语言,在python中使用正则要用re模块 # 例题 # 1. re模块中常用的方法:find all,match,search # 2. match和search的区别 # match从头开始匹配,search整体匹配 # 3. findall # findall:分组优先展示,不会展示所有正则表达式匹配到的内容,仅仅展示括号内正则表达式匹配到的内容 # 4. 贪婪匹配和非贪婪匹配 # 正则表达式默认都是贪婪匹配,要变成非贪婪,只需要在正则表达式的后面加一个问号? .* 贪婪 .*? 非贪婪 select * from emp where name regexp '^j.*n$';
-
多表查询
# 连接表操作 inner join, left join, right join, union # inner join 只拼接两张表中公有的部分 # left join 左表全部显示,右表没有对应的用null填充 # right join :left join反过来 # union:左右全部显示 select * from emp inner join dep on emp。dep_id = dep.id # 要加上表的前缀,不然容易造成冲突
-
子查询
# 我们平时解决问题的思路:分布处理:上一个查询结果当作下一个查询的条件 # 当作条件的时候用括号括起来 select * from emp where id in (select id from dep);
-
总结
# 写sql语句的时候,select后面先用 * 占位,之后写完再改 # 在写较为复杂的sql语句的时候,不要想着一口气写完 # 在做多表查询的时候,联表操作和子查询可能会结合使用
知识点补充
-
查询平均年龄在25岁以上的部门名称
# 部门表dep,员工表emp # 只要是多表查询,就会有两种思路:联表,子查询 # 联表查询 # 1. 先拿到部门和员工表,拼接之后的结果 # 2. 按照部门分组 select dep.name from emp inner join dep on emp.dep_id = dep.id group by dep.name having avg(age) > 25; # 涉及到多表操作的时候,一定要加上表的前缀 # 子查询 select name from dep where id in(select dep_id from emp group by dep_id havingavg(age) > 25);
今日内容概要
- navicat可视化界面
- 数据库查询题目讲解(多表操作)
- python如何操作mysql:pymysql模块
- sql注入问题
- pymysql模块增删改查数据操作
navicat软件
类似pycharm于python,用于更方便地操作MySQL。内部封住了navicat命令,鼠标就可以完成,不用写sql语句
navicat能够充当多个数据库的客户端
当有需求没法满足的时候,自己动手写sql预览里的sql语句
逆向数据库到模型,生成一个模型界面,可以看到表与表之间
提示
-
MySQL不区分大小写
-
MySQL建议所有的关键字:select,group by 建议写大写
-
MySQL注释有两种
ctrl + ? #
开始写题
-
查询所有的课程名称以及对应的老师姓名
# 涉及到course,teacher表:先连起来两张表 select * from course inner join teacher on course.teacher_id = teacher.tid # 分析需求,只想要course表下的cname和teacher表下的tname # 改: SELECT course.cname, teacher.tname FROM course INNER JOIN teacher ON course.teacher_id = teacher.tid
-
查询平均成绩大于80分的同学的姓名和平均成绩
# 涉及到score,student表 select * from score inner join student on score.student_id = student.sid; # 需求:平均成绩>80,姓名,成绩:avg,在group by后使用 ...
-
查询没有报李平老师课的学生姓名
# 涉及course,teacher,student表,需要分步操作 # 1. 先找李平老师的id # 2. 再找所有报了李平老师的id # 3. 再在学生表里面取反 select * from score_id in ( select course.cid from teacher inner join course on teacher.tid = course.teacher_id where teacher.tname = '李平老师'); # 改: SELECT student.sname FROM student WHERE sid NOT IN ( SELECT DISTINCT score.student_id FROM score WHERE score.course_id IN ( SELECT course.cid FROM teacher INNER JOIN course ON teacher.tid = course.teacher_id WHERE teacher.tname = '李平老师' )); # 用正向思维也能写
-
查询没有同时选物理和体育课程的学生姓名
# 只要选了一门的,选了两门的和没有选的都不要 # 涉及student,course表 # 1. 先查物理和体育的id号,再去获取所有选了物理和体育的学生数据 # 2. 按照学生分组,利用聚合函数count筛选出只选了一门的学生id # 3. 依照id获取学生姓名 SELECT student.sname FROM student WHERE student.sid IN ( SELECT score.student_id FROM score WHERE score.course_id IN ( SELECT course.cid FROM course WHERE course.cname IN ( '物理', '体育' )) GROUP BY score.student_id HAVING count( score.course_id ) = 1 );
-
查询挂科超过2门(包括两门)的学生姓名和班级
# 涉及表score,student,挂科,score.num < 60 # 1. 先筛选所有分数小于60的数据 select * from score where score.num < 60; # 2. 按照学生分组,对学生计数,获取大于等于2的学生 group by score.student_id having count(score.course_id )>= 2; # 3. 拼接 # 改: SELECT class.caption, student.sname FROM class INNER JOIN student ON class.cid = student.class_id WHERE student.sid IN ( SELECT score.student_id FROM score WHERE score.num < 60 GROUP BY score.student_id HAVING COUNT( score.course_id ) >= 2 );
pymysql模块
# 首先导入pumysql
import pymysql
conn = pymysql.connect(
host = '127.0.0.1',
post = 3306,
user = root,
password = '6008',
charset = 'utf8' # 编码不要加-,就写utf8
) # 生成conn对象
cursor = conn.cursor() # 产生一个游标对象,用来帮你执行sql命令
sql - 'select * from teacher;'
res = cursor.excute(sql) # 执行
print(res)
# excute返回的结果是当前sql语句影响的行数,该返回值一般不用
# 获取命令执行的查询结果,要通过cursor的方法
print(cursor.fetchone()) # 拿一条结果
# 在生成cursor对象的时候,括号里加参数
cursor = conn.cursor(cursor = pymysql.cursors.DictCursor)
print(cursor.fetchall()) # 拿到sql语句执行的所有
# 括号里面加数字,可以指定拿多少条数据
# 获取结果向文件读取一样,有个指针,移到哪就从哪开始读
# 使用scroll可以控制读取数据的光标
cursor.scroll(1) # 默认移动模式:relative,从当前位置开始前后移动
cursor.scroll(1,'absolute') # 相对于数据开头移动,相当于从头开始读,读一条数据
SQL注入
结合数据库完成一个用户登陆功能
import pymysql
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
password = '123456',
database = 'day48',
charset = 'utf8' # 编码千万不要加-
) # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
username = input('>>>:')
password = input('>>>:')
sql = "select * from user where name=%s and password=%s"
# 不要手动拼接数据 先用%s占位 之后将需要拼接的数据直接交给execute方法即可
print(sql)
rows = cursor.execute(sql,(username,password)) # 自动识别sql里面的%s用后面元组里面的数据替换
if rows:
print('登录成功')
print(cursor.fetchall())
else:
print('用户名密码错误')