第四天(41道题全解) sql注入

41道题:

重要的
连表查询
分组

制表语句:
    班级表
               Table: class
        Create Table: CREATE TABLE `class` (
          `cid` int(11) NOT NULL AUTO_INCREMENT,
          `caption` varchar(50) DEFAULT NULL,
          PRIMARY KEY (`cid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
        1 row in set (0.00 sec)

        
    学生表:
                       Table: student
        Create Table: CREATE TABLE `student` (
          `sid` int(11) NOT NULL AUTO_INCREMENT,
          `sname` varchar(50) DEFAULT NULL,
          `gender` char(10) DEFAULT NULL,
          `class_id` int(11) DEFAULT NULL,
          PRIMARY KEY (`sid`),
          KEY `fk_student_class` (`class_id`),
          CONSTRAINT `fk_student_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
                

    老师表:
                       Table: teacher
        Create Table: CREATE TABLE `teacher` (
          `tid` int(11) NOT NULL AUTO_INCREMENT,
          `tname` varchar(50) DEFAULT NULL,
          PRIMARY KEY (`tid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
        1 row in set (0.00 sec)
                        
                        
    课程表:
                      Table: course
        Create Table: CREATE TABLE `course` (
          `cid` int(11) NOT NULL AUTO_INCREMENT,
          `cname` char(25) DEFAULT NULL,
          `teacher_id` int(11) DEFAULT NULL,
          PRIMARY KEY (`cid`),
          KEY `fk_course_teacher` (`teacher_id`),
          CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
        1 row in set (0.00 sec)

    成绩表:    
            
        create table score
             (sid int not null auto_increment primary key,
              student_id int not null,
             corse_id int not null,
             number int not null,
             unique uq_sc (student_id,corse_id),
             
             CONSTRAINT fk_sc_st FOREIGN key (student_id) REFERENCES student(sid),
             constraint fk_sc_co foreign key  (corse_id) references course(cid)
             ) engine=innodb default charset=utf8;
            
            
    group by前面的slect 只能用聚合函数count,max什么的     
    
    
v= 111 if 1==1 else 110 三元运算符
#########################################################
作业练习:
    http://www.cnblogs.com/wupeiqi/articles/5729934.html    
            
            
http://www.cnblogs.com/wupeiqi/p/5748496.html  参考答案            
            
##########################################################

用到的知识点
- 临时表
        select * from (select * from tb where id< 10) as B;
        
    --- 
        select 
            id,
            name,
            1,
            (select count(1) from tb)----只要拿到的是一个值就可以
        from tb2
    ---把最外层的表s1,每次循环取一个常量值再到每一列中再循环一次    
        SELECT 
            student_id,
            (select num from score as s2 where s2.student_id=s1.student_id and course_id = 1) as 语文,
            (select num from score as s2 where s2.student_id=s1.student_id and course_id = 2) as 数学,
            (select num from score as s2 where s2.student_id=s1.student_id and course_id = 3) as 英语
        from score as s1;            

    ----avg(if(isnull(score.num),0,score.num))
         三目运算符
            
#####################################################
具体作业:
    1、自行创建测试数据

2、查询“生物”课程比“物理”课程成绩高的所有学生的学号;
    PS:查出生物课程的学生,查出物理课程的学生,用临时表,再连接查询
        select A.student_id from 
        (select * from score 
        LEFT JOIN course on score.course_id=course.cid
        where course.cname="生物"
        ) as A
        LEFT JOIN  
        (select * from score 
        LEFT JOIN course on score.course_id=course.cid
        where course.cname="物理"
        ) as B 
        on A.student_id=B.student_id
        where A.num> B.num

3、查询平均成绩大于60分的同学的学号和平均成绩; 
    select student_id, avg(num) from score GROUP BY student_id
    PS:把名字也带上
    select S.student_id,student.sname,S.av_s from 
    (SELECT student_id, avg(num) AS av_s FROM score GROUP BY student_id HAVING av_s > 60) as S
    LEFT JOIN student on student.sid=S.student_id

4、查询所有同学的学号、姓名、选课数、总成绩;
    SELECT score.student_id,student.sname, COUNT(score.student_id),sum(score.num) from score 
    LEFT JOIN student ON score.student_id=student.sid
    GROUP BY score.student_id

5、查询姓“李”的老师的个数;
    select COUNT(*) from teacher where teacher.tname 
    LIKE "李%"

6、查询没学过“李平老师“课的同学的学号、姓名;
    PS:先查找李平的课程ID,再到score表中找学他的课的学生Id,再去student表中全部排除
    select student.sid,student.sname from student
    where student.sid not in 
    (
    select score.student_id from score
    where course_id in (select course.cid from course
    LEFT JOIN teacher on teacher.tid=course.cid
    where teacher.tname="李平老师")
    )

7、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名;
    PS:找出score表中学过课程1,或者2,或者1,2的学生,分组找出大于2的,再与学生表进行连接查询
    select student.sid,student.sname from score
    LEFT JOIN  student on score.student_id=student.sid
     where score.course_id=1 or score.course_id=2 GROUP BY score.student_id HAVING count(score.course_id)>1

8、查询学过“叶平”老师所教的所有课的同学的学号、姓名;
    PS:语句分两部分B表是查出学过叶平老师所有课程的学生ID(注意其中叶平的课程有所变化所以不能count >2)
         再与学生表进行关联
    SELECT student.sid,student.sname FROM student
    LEFT JOIN 
        (
            SELECT score.student_id FROM score WHERE score.course_id 
                IN (
                    SELECT cid FROM course
                    LEFT JOIN teacher ON teacher.tid = course.teacher_id
                    WHERE teacher.tname = "李平老师"
                   ) --查出叶平老师所教的课程的ID 
            GROUP BY score.student_id
            HAVING
                count(score.student_id) = 
                ( 
                    SELECT count(cid) FROM course LEFT JOIN teacher ON teacher.tid = course.teacher_id
                    WHERE teacher.tname = "李平老师" 
                )        --查出叶平老师总共教了几门课count(cid)
        ) AS B             --查出学过叶平老师所有课程的学生ID
    ON student.sid = B.student_id


9、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名;
    PS:
        select student.sid,student.sname from student
        left JOIN 
            (select A.student_id from 
                    (select * from score 
                    LEFT JOIN course on score.course_id=course.cid
                    where course.cid=1
                    ) as A
                    LEFT JOIN  
                    (select * from score 
                    LEFT JOIN course on score.course_id=course.cid
                    where course.cid=2
                    ) as B 
                    on A.student_id=B.student_id
                    where A.num<B.num 
            ) as C 
        on student.sid=C.student_id

10、查询有课程成绩小于60分的同学的学号、姓名;
        select sid,sname from student where sid in (
        select distinct student_id from score where num < 60
    )

11、查询没有学全所有课的同学的学号、姓名;
    PS ---count要嘛用1要嘛用主键,效率高
    SELECT student.sid,student.sname from student
    INNER JOIN 
     (
        select score.student_id,count(1) from score GROUP BY score.student_id HAVING count(1) < (SELECT count(cid) from course)
     ) as B
    on student.sid = B.student_id

12、查询至少有一门课与学号为“001”的同学所学相同的同学的学号和姓名;
    select student.sid,student.sname from student
    INNER JOIN
    (
    SELECT score.student_id,score.course_id from score where score.student_id !=1 
    and  score.course_id in (select score.course_id from score where score.student_id=1) GROUP BY score.student_id
    ) as B
    on student.sid=B.student_id

13、查询至少学过学号为“001”同学所有课的其他同学学号和姓名
    select student.sid,student.sname from student
    INNER  JOIN
    (
        SELECT score.student_id,count(1) from score where score.student_id !=1 
            and  score.course_id in (select score.course_id from score where score.student_id=1) 
        GROUP BY score.student_id 
        HAVING count(1) = (select count(1) from score where score.student_id=1)
        ) AS B
    on student.sid=B.student_id

14、查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名;
    SELECT student_id from score where student_id 
    in (
        select student_id from score where student_id !=2 GROUP BY student_id 
            HAVING COUNT(1) =(select count(1) from score where student_id=1)
        ) 
    and course_id in (SELECT course_id from score where student_id =2) 
    GROUP BY student_id HAVING COUNT(1) = (SELECT count(1) from score where student_id)

15、删除学习“叶平”老师课的SC表记录;
    delete from score where course_id in 
    (
      select cid from course left join teacher on course.teacher_id = teacher.tid where teacher.name = '叶平'
    )

16、向SC表中插入一些记录,这些记录要求符合以下条件:①没有上过编号“002”课程的同学学号;②插入“002”号课程的平均成绩; 
    insert into score(student_id,course_id,num) 
    VALUES(select student_id,2,(select AVG(num) from score where course_id = 2) from score where course_id !=2) 

17、按平均成绩从低到高显示所有学生的“语文”、“数学”、“英语”三门的课程成绩,按如下形式显示: 学生ID,语文,数学,英语,有效课程数,有效平均分;
       select s1.student_id,
       (select num from score left join course on score.course_id = course.cid where course.cname = "生物" and score.student_id=s1.student_id) as 生物,
        (select num from score left join course on score.course_id = course.cid where course.cname = "物理" and score.student_id=s1.student_id) as 物理,
        (select num from score left join course on score.course_id = course.cid where course.cname = "体育" and score.student_id=s1.student_id) as 体育,
        count(s1.course_id),
        avg(s1.num)
    from score as s1
    group by student_id desc

18、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分;
    SELECT course_id,MAX(num),min(num) from score GROUP BY course_id

19、按各科平均成绩从低到高和及格率的百分数从高到低顺序;

            select 
        course_id,avg(num),
        sum(case when num <60 THEN 0 ELSE 1 END),sum(1),
        sum(case when num <60 THEN 0 ELSE 1 END)/sum(1) as jgl 
        from score GROUP BY course_id order by AVG(num) asc,jgl desc;

20、课程平均分从高到低显示(现实任课老师);
        select 
        course_id,avg(num),teacher.tname 
        from score
        LEFT JOIN course on score.course_id=course.cid
        left JOIN teacher on teacher.tid = course.teacher_id
        GROUP BY course_id desc
        
         select avg(if(isnull(score.num),0,score.num)),teacher.tname from course
    left join score on course.cid = score.course_id
    left join teacher on course.teacher_id = teacher.tid
 
    group by score.course_id

21、查询各科成绩前三名的记录:(不考虑成绩并列情况) 

22、查询每门课程被选修的学生数;
SELECT student_id ,count(1) from score GROUP BY course_id HAVING COUNT(1) >5

23、查询出只选修了一门课程的全部学生的学号和姓名;
SELECT  student.sid,student.sname from student
INNER  JOIN 
(SELECT student_id ,count(1) from score GROUP BY student_id HAVING COUNT(1) =1) as B
on student.sid=B.student_id

24、查询男生、女生的人数;
SELECT gender,COUNT(1) from student GROUP BY gender

25、查询姓“张”的学生名单;
SELECT sname from student where sname LIKE "张%"

26、查询同名同姓学生名单,并统计同名人数;
SELECT sname,count(1) from student GROUP BY sname

27、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列;
SELECT course_id,AVG(num) from score GROUP BY score.course_id ORDER BY avg(num) ASC,course_id DESC

28、查询平均成绩大于85的所有学生的学号、姓名和平均成绩;
SELECT sid,sname,T.B from student
INNER  JOIN
(SELECT student_id ,avg(if(ISNULL(num) ,0,num)) as B from score GROUP BY student_id HAVING B >85) as T
on T.student_id=student.sid

29、查询课程名称为“生物”,且分数低于60的学生姓名和分数;
    SELECT student.sname,score.num from course
    LEFT JOIN score on course.cid=score.course_id
    LEFT JOIN student on student.sid=score.student_id
     
    where course.cname='生物' and score.num < 60

30、查询课程编号为003且课程成绩在80分以上的学生的学号和姓名;

    SELECT student.sname,score.num from course
    LEFT JOIN score on course.cid=score.course_id
    LEFT JOIN student on student.sid=score.student_id
    where course.cid=3 and score.num >80 

31、求选了课程的学生人数
SELECT count(DISTINCT(score.student_id)) from score

32、查询选修“李平”老师所授课程的学生中,成绩最高的学生姓名及其成绩;

SELECT student.sname,T.num from student
INNER  JOIN 
(SELECT * from teacher 
LEFT JOIN course on teacher.tid=course.teacher_id
LEFT JOIN score on score.course_id=course.cid
 GROUP BY num HAVING teacher.tname="张磊老师"  ORDER BY  num DESC LIMIT 0,1) as T
on student.sid= T.student_id

33、查询各个课程及相应的选修人数;
 select course.cname,count(1) from score
    left join course on score.course_id = course.cid
    group by course_id;

34、查询不同课程但成绩相同的学生的学号、课程号、学生成绩;
SELECT DISTINCT s1.student_id,s1.course_id,s1.num from score as s1,score as s2 WHERE s1.sid !=s2.sid and s1.course_id !=s2.course_id and s1.num=s2.num

35、查询每门课程成绩最好的前两名;
 select score.sid,score.course_id,score.num,T.first_num,T.second_num from score left join
    (
    select
        sid,
        (select num from score as s2 where s2.course_id = s1.course_id order by num desc limit 0,1) as first_num,
        (select num from score as s2 where s2.course_id = s1.course_id order by num desc limit 1,1) as second_num
    from
        score as s1
    ) as T
    on score.sid =T.sid
    where score.num <= T.first_num and score.num >= T.second_num

36、检索至少选修两门课程的学生学号;
SELECT student_id from score GROUP BY student_id HAVING count(student_id) >1

37、查询全部学生都选修的课程的课程号和课程名;

38、查询没学过“叶平”老师讲授的任一门课程的学生姓名;
    PS:先查出学过李平老师任意一门课的学生,包括只选了一门的,然后,全部排除
    SELECT student.sid from student
    WHERE sid not in(
    SELECT score.student_id from score
    WHERE course_id in
    (
    SELECT  course.cid from course
     LEFT JOIN teacher on course.teacher_id=teacher.tid WHERE teacher.tname="李平老师"
     ))

39、查询两门以上不及格课程的同学的学号及其平均成绩;
 select student_id,count(1) from score where num < 60 group by student_id having count(1) > 2

40、检索“004”课程分数小于60,按分数降序排列的同学学号;
   select student_id from score where num< 60 and course_id = 4 order by num desc;

41、删除“002”同学的“001”课程的成绩;
    delete from score where course_id = 1 and student_id = 2
View Code

   sql注入代码样例:

import pymysql

user = input("username:")
pwd = input("password:")

conn = pymysql.connect(host="localhost",user='root',password='',database="db666")
cursor = conn.cursor()
sql = "select * from userinfo where username='%s' and password='%s'" %(user,pwd,)
# select * from userinfo where username='uu' or 1=1 -- ' and password='%s'  
#根本的原因是因为有--注释掉后passwor,而1=1是永真,所以一定不能自己来拼接用户名密码
cursor.execute(sql)
result = cursor.fetchone()
cursor.close()
conn.close()

if result:
    print('登录成功')
else:
    print('登录失败')
View Code

为防止sql注入应当使用pymysql自带的excute的参数传递,支持字典,列表,字符串

import pymysql

user = input("username:")
pwd = input("password:")

conn = pymysql.connect(host="localhost",user='root',password='',database="db666")
cursor = conn.cursor()
sql = "select * from userinfo where username=%s and password=%s"
#sql = "select * from userinfo where username=%(u)s and password=%(p)s"
cursor.execute(sql,user,pwd)  #防止sql注入的方法
# cursor.execute(sql,[user,pwd])
# cursor.execute(sql,{'u':user,'p':pwd})
result = cursor.fetchone()
cursor.close()
conn.close()
if result:
    print('登录成功')
else:
    print('登录失败')
View Code

 

sql多行插入

 1 import pymysql
 2 
 3 # 增加,删,该
 4 #conn = pymysql.connect(host="localhost",user='root',password='',database="db1")
 5 #cursor = conn.cursor()
 6 #sql = "insert into userinfo(username,password) values('root','123123')"
 7 ## 受影响的行数
 8 #r = cursor.execute(sql)
 9 # #  ******
10 #conn.commit()
11 #cursor.close()
12 #conn.close()
13 
14 conn = pymysql.connect(host="localhost",user='root',password='',database="db1")
15 cursor = conn.cursor()
16 # # sql = "insert into userinfo(username,password) values(%s,%s)"
17 # # cursor.execute(sql,(user,pwd,))
18 #
19 sql = "insert into userinfo(username,password) values(%s,%s)"
20 # r 是 受影响的行数
21 r = cursor.executemany(sql,[('egon','sb'),('laoyao','BS')])
22 # #  ******
23 conn.commit()
24 cursor.close()
25 conn.close()
26 "s3.p
View Code

 

pymysql模块:
pip3 install pymysql -i https://pypi.douban.com/simple
Python模块:对数据库进行操作(SQL语句)

1. Python实现用户登录
2. MySQL保存数据


- 连接、关闭(游标)
- execute() -- SQL注入
- 增删改: conn.commit()
- fetchone fetchall
- 获取插入数据自增ID

posted @ 2017-12-20 22:26  wanchenxi  阅读(268)  评论(0编辑  收藏  举报