数据库

首页 » 常识 » 预防 » 20000字干货笔记,一天搞定MySQL
TUhjnbcbe - 2025/2/26 13:08:00
白癜风怎么治好得快 http://www.xxzywj.com/m/

作者

远辰

本文为「数据不吹牛」投稿

今天给大家分享的是我学习MySQL记录的详细笔记,有基础知识,也有实战案例,文章较长,建议收藏~

基本语法

--显示所有数据库showdatabases;--创建数据库CREATEDATABASEtest;--切换数据库usetest;--显示数据库中的所有表showtables;--创建数据表CREATETABLEpet(nameVARCHAR(20),ownerVARCHAR(20),speciesVARCHAR(20),sexCHAR(1),birthDATE,deathDATE);--查看数据表结构--describepet;descpet;--查询表SELECT*frompet;--插入数据INSERTINTOpetVALUES(puffball,Diane,hamster,f,-03-30,NULL);--修改数据UPDATEpetSETname=squirrelwhereowner=Diane;--删除数据DELETEFROMpetwherename=squirrel;--删除表DROPTABLEmyorder;

数据库大三大设计范式

1NF不可分割性,只要字段值还可以继续拆分,就不满足第一范式。

不可分割的意思就按字面理解就是最小单位,不能再分成更小单位了。

字段只能是一个值,不能被拆分成多个字段,否则的话,它就是可分割的,就不符合一范式。

2NF第二范式就是要有主键,要求其他字段都依赖于主键。

为什么要有主键?没有主键就没有唯一性,没有唯一性在集合中就定位不到这行记录,所以要主键。

在满足第一范式的前提下,主键外的每一列都必须完全依赖于主键。如果出现不完全依赖,只可能发生在联合主键的情况下。

3NF在满足第二范式的前提下,除了主键列之外,其他列之间不能有传递依赖关系,即“消除冗余”。

消除冗余,就是各种信息只在一个地方存储,不出现在多张表中。

范式总结:范式,其实是用来学习参考的,设计的时候根据情况,未必一定要遵守,要灵活结合业务实际情况决定。

查询练习

准备数据--创建数据库CREATEDATABASEselect_test;--切换数据库USEselect_test;--创建学生表CREATETABLEstudent(noVARCHAR(20)PRIMARYKEY,nameVARCHAR(20)NOTNULL,sexVARCHAR(10)NOTNULL,birthdayDATE,--生日classVARCHAR(20)--所在班级);--创建教师表CREATETABLEteacher(noVARCHAR(20)PRIMARYKEY,nameVARCHAR(20)NOTNULL,sexVARCHAR(10)NOTNULL,birthdayDATE,professionVARCHAR(20)NOTNULL,--职称departmentVARCHAR(20)NOTNULL--部门);--创建课程表CREATETABLEcourse(noVARCHAR(20)PRIMARYKEY,nameVARCHAR(20)NOTNULL,t_noVARCHAR(20)NOTNULL,--教师编号--表示该tno来自于teacher表中的no字段值FOREIGNKEY(t_no)REFERENCESteacher(no));--成绩表CREATETABLEscore(s_noVARCHAR(20)NOTNULL,--学生编号c_noVARCHAR(20)NOTNULL,--课程号degreeDECIMAL,--成绩--表示该s_no,c_no分别来自于student,course表中的no字段值FOREIGNKEY(s_no)REFERENCESstudent(no),FOREIGNKEY(c_no)REFERENCEScourse(no),--设置s_no,c_no为联合主键PRIMARYKEY(s_no,c_no));--查看所有表SHOWTABLES;--添加学生表数据INSERTINTOstudentVALUES(,曾华,男,-09-01,);INSERTINTOstudentVALUES(,匡明,男,-10-02,);INSERTINTOstudentVALUES(,王丽,女,-01-23,);INSERTINTOstudentVALUES(,李军,男,-02-20,);INSERTINTOstudentVALUES(,王芳,女,-02-10,);INSERTINTOstudentVALUES(,陆军,男,-06-03,);INSERTINTOstudentVALUES(,王尼玛,男,-02-20,);INSERTINTOstudentVALUES(,张全蛋,男,-02-10,);INSERTINTOstudentVALUES(,赵铁柱,男,-06-03,);--添加教师表数据INSERTINTOteacherVALUES(,李诚,男,-12-02,副教授,计算机系);INSERTINTOteacherVALUES(,张旭,男,-03-12,讲师,电子工程系);INSERTINTOteacherVALUES(,王萍,女,-05-05,助教,计算机系);INSERTINTOteacherVALUES(,刘冰,女,-08-14,助教,电子工程系);--添加课程表数据INSERTINTOcourseVALUES(3-,计算机导论,);INSERTINTOcourseVALUES(3-,操作系统,);INSERTINTOcourseVALUES(6-,数字电路,);INSERTINTOcourseVALUES(9-,高等数学,);--添加添加成绩表数据INSERTINTOscoreVALUES(,3-,92);INSERTINTOscoreVALUES(,3-,86);INSERTINTOscoreVALUES(,6-,85);INSERTINTOscoreVALUES(,3-,88);INSERTINTOscoreVALUES(,3-,75);INSERTINTOscoreVALUES(,6-,79);INSERTINTOscoreVALUES(,3-,76);INSERTINTOscoreVALUES(,3-,68);INSERTINTOscoreVALUES(,6-,81);--查看表结构SELECT*FROMcourse;SELECT*FROMscore;SELECT*FROMstudent;SELECT*FROMteacher;

基础查询--查询student表的所有行SELECT*FROMstudent;--查询student表中的name、sex和class字段的所有行SELECTname,sex,classFROMstudent;--查询teacher表中不重复的department列--department:去重查询SELECTDISTINCTdepartmentFROMteacher;--查询score表中成绩在60-80之间的所有行(区间查询和运算符查询)--BETWEENxxANDxx:查询区间,AND表示并且SELECT*FROMscoreWHEREdegreeBETWEEN60AND80;SELECT*FROMscoreWHEREdegree60ANDdegree80;--查询score表中成绩为85,86或88的行--IN:查询规定中的多个值SELECT*FROMscoreWHEREdegreeIN(85,86,88);--查询student表中班或性别为女的所有行--or:表示或者关系SELECT*FROMstudentWHEREclass=orsex=女;--以class降序的方式查询student表的所有行--DESC:降序,从高到低--ASC(默认):升序,从低到高SELECT*FROMstudentORDERBYclassDESC;SELECT*FROMstudentORDERBYclassASC;--以c_no升序、degree降序查询score表的所有行SELECT*FROMscoreORDERBYc_noASC,degreeDESC;--查询班的学生人数--COUNT:统计SELECTCOUNT(*)FROMstudentWHEREclass=;--查询score表中的最高分的学生学号和课程编号(子查询或排序查询)。--(SELECTMAX(degree)FROMscore):子查询,算出最高分SELECTs_no,c_noFROMscoreWHEREdegree=(SELECTMAX(degree)FROMscore);--排序查询--LIMITr,n:表示从第r行开始,查询n条数据SELECTs_no,c_no,degreeFROMscoreORDERBYdegreeDESCLIMIT0,1;--LIMITnoffsetr:表示查询n条数据,从第r行开始SELECTs_no,c_no,degreeFROMscoreORDERBYdegreeDESCLIMIT1offse

分组计算平均成绩查询每门课的平均成绩

--AVG:平均值SELECTAVG(degree)FROMscoreWHEREc_no=3-;SELECTAVG(degree)FROMscoreWHEREc_no=3-;SELECTAVG(degree)FROMscoreWHEREc_no=6-;--GROUPBY:分组查询SELECTc_no,AVG(degree)FROMscoreGROUPBYc_no;

分组条件与模糊查询查询score表中至少有2名学生选修,并以3开头的课程的平均分数

分析表发现,至少有2名学生选修的课程是3-、3-、6-,以3开头的课程是3-、3-。也就是说,我们要查询所有3-和3-的degree平均分。

--首先把c_no,AVG(degree)通过分组查询出来SELECTc_no,AVG(degree)FROMscoreGROUPBYc_no+-------+-------------+

c_no

AVG(degree)

+-------+-------------+

3-

85.

3-

76.

6-

81.

+-------+-------------+--再查询出至少有2名学生选修的课程--HAVING:表示持有HAVINGCOUNT(c_no)=2--并且是以3开头的课程--LIKE表示模糊查询,%是一个通配符,匹配3后面的任意字符。ANDc_noLIKE3%;--把前面的SQL语句拼接起来,--后面加上一个COUNT(*),表示将每个分组的个数也查询出来。SELECTc_no,AVG(degree),COUNT(*)FROMscoreGROUPBYc_noHAVINGCOUNT(c_no)=2ANDc_noLIKE3%;+-------+-------------+----------+

c_no

AVG(degree)

COUNT(*)

+-------+-------------+----------+

3-

85.

3

3-

76.

3

+-------+-------------+----------+

多表查询-1查询所有学生的name,以及该学生在score表中对应的c_no和degree

SELECTno,nameFROMstudent;+-----+-----------+

no

name

+-----+-----------+

曾华

匡明

王丽

李军

王芳

陆军

王尼玛

张全蛋

赵铁柱

+-----+-----------+SELECTs_no,c_no,degreeFROMscore;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

92

3-

86

6-

85

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+

通过分析可以发现,只要把score表中的s_no字段值替换成student表中对应的name字段值就可以了,如何做呢?

--FROM...:表示从student,score表中查询--WHERE的条件表示为,只有在student.no和score.s_no相等时才显示出来。SELECTname,c_no,degreeFROMstudent,scoreWHEREstudent.no=score.s_no;+-----------+-------+--------+

name

c_no

degree

+-----------+-------+--------+

王丽

3-

92

王丽

3-

86

王丽

6-

85

王芳

3-

88

王芳

3-

75

王芳

6-

79

赵铁柱

3-

76

赵铁柱

3-

68

赵铁柱

6-

81

+-----------+-------+--------+

多表查询-2查询所有学生的no、课程名称(course表中的name)和成绩(score表中的degree)列。

只有score关联学生的no,因此只要查询score表,就能找出所有和学生相关的no和degree:

SELECTs_no,c_no,degreeFROMscore;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

92

3-

86

6-

85

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+

然后查询course表:

SELECTno,nameFROMcourse;+-------+-----------------+

no

name

+-------+-----------------+

3-

计算机导论

3-

操作系统

6-

数字电路

9-

高等数学

+-------+-----------------+

只要把score表中的c_no替换成course表中对应的name字段值就可以了。

--增加一个查询字段name,分别从score、course这两个表中查询。--as表示取一个该字段的别名。SELECTs_no,nameasc_name,degreeFROMscore,courseWHEREscore.c_no=course.no;+------+-----------------+--------+

s_no

c_name

degree

+------+-----------------+--------+

计算机导论

92

计算机导论

88

计算机导论

76

操作系统

86

操作系统

75

操作系统

68

数字电路

85

数字电路

79

数字电路

81

+------+-----------------+--------+

三表关联查询查询所有学生的name、课程名(course表中的name)和degree。

只有score表中关联学生的学号和课堂号,我们只要围绕着score这张表查询就好了。

SELECT*FROMscore;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

92

3-

86

6-

85

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+

只要把s_no和c_no替换成student和course表中对应的name字段值就好了。

首先把s_no替换成student表中的name字段:

SELECTname,c_no,degreeFROMstudent,scoreWHEREstudent.no=score.s_no;+-----------+-------+--------+

name

c_no

degree

+-----------+-------+--------+

王丽

3-

92

王丽

3-

86

王丽

6-

85

王芳

3-

88

王芳

3-

75

王芳

6-

79

赵铁柱

3-

76

赵铁柱

3-

68

赵铁柱

6-

81

+-----------+-------+--------+

再把c_no替换成course表中的name字段:

--课程表SELECTno,nameFROMcourse;+-------+-----------------+

no

name

+-------+-----------------+

3-

计算机导论

3-

操作系统

6-

数字电路

9-

高等数学

+-------+-----------------+--由于字段名存在重复,使用表名.字段名as别名代替。SELECTstudent.nameass_name,course.nameasc_name,degreeFROMstudent,score,courseWHEREstudent.NO=score.s_noANDscore.c_no=course.no;

子查询加分组求平均分查询班学生每门课程的平均成绩。

在score表中根据student表的学生编号筛选出学生的课堂号和成绩:

--IN(..):将筛选出的学生号当做s_no的条件查询SELECTs_no,c_no,degreeFROMscoreWHEREs_noIN(SELECTnoFROMstudentWHEREclass=);+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+

这时只要将c_no分组一下就能得出班学生每门课的平均成绩:

SELECTc_no,AVG(degree)FROMscoreWHEREs_noIN(SELECTnoFROMstudentWHEREclass=)GROUPBYc_no;+-------+-------------+

c_no

AVG(degree)

+-------+-------------+

3-

82.

3-

71.

6-

80.

+-------+-------------+

子查询-1查询在3-课程中,所有成绩高于号同学的记录。

先用子查询查找出同学在3-中的成绩

select*fromscorewherec_no=3-ands_no=

然后再以课程3-为条件,查找成绩大76的记录

select*fromscorewherec_no=3-anddegree(selectdegreefromscorewherec_no=3-ands_no=);

子查询-2查询所有成绩高于号同学的3-课程成绩记录。

--不限制课程号,只要成绩大于号同学的3-课程成绩就可以。SELECT*FROMscoreWHEREdegree(SELECTdegreeFROMscoreWHEREs_no=ANDc_no=3-);

YEAR函数与带IN关键字查询查询所有和、号学生同年出生的no、name、birthday列。

selectno,name,birthdayfromstudentwhereyear(birthday)in(selectyear(birthday)fromstudentwherenoin(,));

多层嵌套子查询查询张旭教师任课的学生成绩表。

用的三张表teacher、course、score,首先找到教师编号:

SELECTNOFROMteacherWHERENAME=张旭

通过sourse表找到该教师课程号:

selectnofromcoursewheret_no=(SELECTNOFROMteacherWHERENAME=张旭)

通过筛选出的课程号查询成绩表:

select*fromscorewherec_no=(selectnofromcoursewheret_no=(selectnofromteacherwherename=张旭));

多表查询查询某选修课程多于5个同学的教师姓名。

首先在teacher表中,根据no字段来判断该教师的同一门课程是否有至少5名学员选修:

--查询teacher表SELECTno,nameFROMteacher;+-----+--------+

no

name

+-----+--------+

李诚

王萍

刘冰

张旭

+-----+--------+SELECTnameFROMteacherWHEREnoIN(--在这里找到对应的条件);

查看和教师编号有有关的表的信息:

SELECT*FROMcourse;--t_no:教师编号+-------+-----------------+------+

no

name

t_no

+-------+-----------------+------+

3-

计算机导论

3-

操作系统

6-

数字电路

9-

高等数学

+-------+-----------------+------+

我们已经找到和教师编号有关的字段就在course表中,但是还无法知道哪门课程至少有5名学生选修,所以还需要根据score表来查询:

--在此之前向score插入一些数据,以便丰富查询条件。INSERTINTOscoreVALUES(,3-,90);INSERTINTOscoreVALUES(,3-,91);INSERTINTOscoreVALUES(,3-,89);--查询score表SELECT*FROMscore;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

90

3-

91

3-

92

3-

86

6-

85

3-

89

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+--在score表中将c_no作为分组,并且限制c_no持有至少5条数据。SELECTc_noFROMscoreGROUPBYc_noHAVINGCOUNT(*)5;+-------+

c_no

+-------+

3-

+-------+

根据筛选出来的课程号,找出在某课程中,拥有至少5名学员的教师编号:

SELECTt_noFROMcourseWHEREnoIN(SELECTc_noFROMscoreGROUPBYc_noHAVINGCOUNT(*)5);+------+

t_no

+------+

+------+在teacher表中,根据筛选出来的教师编号找到教师姓名:SELECTnameFROMteacherWHEREnoIN(--最终条件SELECTt_noFROMcourseWHEREnoIN(SELECTc_noFROMscoreGROUPBYc_noHAVINGCOUNT(*)5));

子查询-3查询“计算机系”课程的成绩表。

思路是,先找出teacher表中所有计算机系课程的编号,根据这个编号查询course表中的课程编号,再用课程编号查找score表

--通过teacher表查询所有`计算机系`的教师编号SELECTno,name,departmentFROMteacherWHEREdepartment=计算机系+-----+--------+--------------+

no

name

department

+-----+--------+--------------+

李诚

计算机系

王萍

计算机系

+-----+--------+--------------+--通过course表查询该教师的课程编号SELECTnoFROMcourseWHEREt_noIN(SELECTnoFROMteacherWHEREdepartment=计算机系);+-------+

no

+-------+

3-

3-

+-------+--根据筛选出来的课程号查询成绩表SELECT*FROMscoreWHEREc_noIN(SELECTnoFROMcourseWHEREt_noIN(SELECTnoFROMteacherWHEREdepartment=计算机系));+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

86

3-

75

3-

68

3-

90

3-

91

3-

92

3-

89

3-

88

3-

76

+------+-------+--------+

UNION和NOTIN的使用查询计算机系与电子工程系中的不同职称的教师。

+-----+------+-----+------------+------------+------------+

no

name

sex

birthday

profession

department

+-----+------+-----+------------+------------+------------+

李诚

-12-02

副教授

计算机系

王萍

-05-05

助教

计算机系

刘冰

-08-14

助教

电子工程系

张旭

-03-12

讲师

电子工程系

+-----+------+-----+------------+------------+------------+--NOT:代表逻辑非SELECT*FROMteacherWHEREdepartment=计算机系ANDprofessionNOTIN(SELECTprofessionFROMteacherWHEREdepartment=电子工程系)--合并两个集UNIONSELECT*FROMteacherWHEREdepartment=电子工程系ANDprofessionNOTIN(SELECTprofessionFROMteacherWHEREdepartment=计算机系);

ANY表示至少一个-DESC(降序)查询课程3-且成绩至少高于3-的score表。

SELECT*FROMscoreWHEREc_no=3-;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

90

3-

91

3-

92

3-

89

3-

88

3-

76

+------+-------+--------+SELECT*FROMscoreWHEREc_no=3-;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

86

3-

75

3-

68

+------+-------+--------+--ANY:符合SQL语句中的任意条件。--也就是说,在3-成绩中,只要有一个大于从3-筛选出来的任意行就符合条件,--最后根据降序查询结果。SELECT*FROMscoreWHEREc_no=3-ANDdegreeANY(SELECTdegreeFROMscoreWHEREc_no=3-)ORDERBYdegreeDESC;+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

92

3-

91

3-

90

3-

89

3-

88

3-

76

+------+-------+--------+

表示所有的ALL查询课程3-且成绩高于3-的score表。

--只需对上一道题稍作修改。--ALL:符合SQL语句中的所有条件。--也就是说,在3-每一行成绩中,都要大于从3-筛选出来全部行才算符合条件。SELECT*FROMscoreWHEREc_no=3-ANDdegreeALL(SELECTdegreeFROMscoreWHEREc_no=3-);+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

90

3-

91

3-

92

3-

89

3-

88

+------+-------+--------+

复制表的数据作为条件查询查询某课程成绩比该课程平均成绩低的score表。

--查询平均分SELECTc_no,AVG(degree)FROMscoreGROUPBYc_no;b表+-------+-------------+

c_no

AVG(degree)

+-------+-------------+

3-

87.

3-

76.

6-

81.

+-------+-------------+--查询score表select*fromscore;a表+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

90

3-

91

3-

92

3-

86

6-

85

3-

89

3-

88

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+--将表b作用于表a中查询数据--scorea(b):将表声明为a(b),--如此就能用a.c_no=b.c_no作为条件执行查询了。SELECT*FROMscoreaWHEREdegree((SELECTAVG(degree)FROMscorebWHEREa.c_no=b.c_no));+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

75

6-

79

3-

76

3-

68

6-

81

+------+-------+--------+

子查询-4查询所有任课(在course表里有课程)教师的name和department。

SELECTname,departmentFROMteacherWHEREnoIN(SELECTt_noFROMcourse);+--------+-----------------+

name

department

+--------+-----------------+

李诚

计算机系

王萍

计算机系

刘冰

电子工程系

张旭

电子工程系

+--------+-----------------+

条件加组筛选查询student表中至少有2名男生的class。

--查看学生表信息SELECT*FROMstudent;+-----+-----------+-----+------------+-------+

no

name

sex

birthday

class

+-----+-----------+-----+------------+-------+

曾华

-09-01

匡明

-10-02

王丽

-01-23

李军

-02-20

王芳

-02-10

陆军

-06-03

王尼玛

-02-20

张全蛋

-02-10

赵铁柱

-06-03

张飞

-06-03

+-----+-----------+-----+------------+-------+--只查询性别为男,然后按class分组,并限制class行大于1。select*fromstudentwheresex=男groupbyclasshavingcount(class)=2;+-----+------+-----+------------+-------+

no

name

sex

birthday

class

+-----+------+-----+------------+-------+

曾华

-09-01

匡明

-10-02

+-----+------+-----+------------+-------+

NOTLIKE模糊查询取反查询student表中不姓王的同学记录。

--NOT:取反--LIKE:模糊查询mysqlSELECT*FROMstudentWHEREnameNOTLIKE王%;+-----+-----------+-----+------------+-------+

no

name

sex

birthday

class

+-----+-----------+-----+------------+-------+

曾华

-09-01

匡明

-10-02

李军

-02-20

陆军

-06-03

张全蛋

-02-10

赵铁柱

-06-03

张飞

-06-03

+-----+-----------+-----+------------+-------+

YEAR与NOW函数查询student表中每个学生的姓名和年龄。

selectname,year(now())-year(birthday)asagefromstudent;+-----------+------+

name

age

+-----------+------+

曾华

42

匡明

44

王丽

43

李军

43

王芳

44

陆军

45

王尼玛

43

张全蛋

44

赵铁柱

45

张飞

45

+-----------+------+

MAX与MIN函数查询student表中最大和最小的birthday值。

SELECTMAX(birthday),MIN(birthday)FROMstudent;+---------------+---------------+

MAX(birthday)

MIN(birthday)

+---------------+---------------+

-09-01

-06-03

+---------------+---------------+

多段排序以class和birthday从大到小的顺序查询student表。

SELECT*FROMstudentORDERBYclassDESC,birthdayDESC;+-----+--------+-----+------------+-------+

no

name

sex

birthday

class

+-----+--------+-----+------------+-------+

张飞

-06-03

曾华

-09-01

李军

-02-20

王尼玛

-02-20

王丽

-01-23

匡明

-10-02

王芳

-02-10

张全蛋

-02-10

陆军

-06-03

赵铁柱

-06-03

+-----+--------+-----+------------+-------+

子查询-5查询男教师及其所上的课程。

SELECT*FROMcourseWHEREt_noin(SELECTnoFROMteacherWHEREsex=男);+-------+--------------+------+

no

name

t_no

+-------+--------------+------+

3-

操作系统

6-

数字电路

+-------+--------------+------+

MAX函数与子查询查询最高分同学的score表。

--找出最高成绩(该查询只能有一个结果)SELECTMAX(degree)FROMscore;--根据上面的条件筛选出所有最高成绩表,--该查询可能有多个结果,假设degree值多次符合条件。SELECT*FROMscoreWHEREdegree=(SELECTMAX(degree)FROMscore);+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

92

+------+-------+--------+

子查询-6查询和李军同性别的所有同学name。

selectnamefromstudentwheresex=(SELECTsexFROMstudentwherename=李军);+--------+

name

+--------+

曾华

匡明

李军

陆军

王尼玛

张全蛋

赵铁柱

张飞

+--------+

子查询-7查询和李军同性别且同班的同学name。

SELECTname,sex,classFROMstudentWHEREsex=(SELECTsexFROMstudentWHEREname=李军)ANDclass=(SELECTclassFROMstudentWHEREname=李军);+-----------+-----+-------+

name

sex

class

+-----------+-----+-------+

曾华

李军

王尼玛

+-----------+-----+-------+

子查询-8查询所有选修计算机导论课程的男同学成绩表。

需要的计算机导论和性别为男的编号可以在course和student表中找到。

SELECT*FROMscoreWHEREc_no=(SELECTnoFROMcourseWHEREname=计算机导论)ANDs_noIN(SELECTnoFROMstudentWHEREsex=男);+------+-------+--------+

s_no

c_no

degree

+------+-------+--------+

3-

90

3-

91

3-

89

3-

76

+------+-------+--------+

按等级查询建立一个grade表代表学生的成绩等级,并插入数据:

CREATETABLEgrade(lowINT(3),uppINT(3),gradechar(1));INSERTINTOgradeVALUES(90,,A);INSERTINTOgradeVALUES(80,89,B);INSERTINTOgradeVALUES(70,79,C);INSERTINTOgradeVALUES(60,69,D);INSERTINTOgradeVALUES(0,59,E);SELECT*FROMgrade;+------+------+-------+

low

upp

grade

+------+------+-------+

90

A

80

89

B

70

79

C

60

69

D

0

59

E

+------+------+-------+

查询所有学生的s_no、c_no和grade列。思路是,使用区间(BETWEEN)查询,判断学生的成绩(degree)在grade表的low和upp之间。

SELECTs_no,c_no,gradeFROMscore,gradeWHEREdegreeBETWEENlowANDupp;+------+-------+-------+

s_no

c_no

grade

+------+-------+-------+

3-

A

3-

A

3-

A

3-

B

6-

B

3-

B

3-

B

3-

C

6-

C

3-

C

3-

D

6-

B

+------+-------+-------+

连接查询准备用于测试连接查询的数据:

CREATEDATABASEtestJoin;CREATETABLEperson(idINT,nameVARCHAR(20),cardIdINT);CREATETABLEcard(idINT,nameVARCHAR(20));INSERTINTOcardVALUES(1,饭卡),(2,建行卡),(3,农行卡),(4,工商卡),(5,邮政卡);SELECT*FROMcard;+------+-----------+

id

name

+------+-----------+

1

饭卡

2

建行卡

3

农行卡

4

工商卡

5

邮政卡

+------+-----------+INSERTINTOpersonVALUES(1,张三,1),(2,李四,3),(3,王五,6);SELECT*FROMperson;+------+--------+--------+

id

name

cardId

+------+--------+--------+

1

张三

1

2

李四

3

3

王五

6

+------+--------+--------+

分析两张表发现,person表并没有为cardId字段设置一个在card表中对应的id外键。如果设置了的话,person中cardId字段值为6的行就插不进去,因为该cardId值在card表中并没有。

内连接要查询这两张表中有关系的数据,可以使用INNERJOIN(内连接)将它们连接在一起。

--INNERJOIN:表示为内连接,将两张表拼接在一起。--on:表示要执行某个条件。SELECT*FROMpersonINNERJOINcardonperson.cardId=card.id;+------+--------+--------+------+-----------+

id

name

cardId

id

name

+------+--------+--------+------+-----------+

1

张三

1

1

饭卡

2

李四

3

3

农行卡

+------+--------+--------+------+-----------+--将INNER关键字省略掉,结果也是一样的。--SELECT*FROMpersonJOINcardonperson.cardId=card.id;注意:card的整张表被连接到了右边。

左外连接完整显示左边的表(person),右边的表如果符合条件就显示,不符合则补NULL。

--LEFTJOIN也叫做LEFTOUTERJOIN,用这两种方式的查询结果是一样的。SELECT*FROMpersonLEFTJOINcardonperson.cardId=card.id;+------+--------+--------+------+-----------+

id

name

cardId

id

name

+------+--------+--------+------+-----------+

1

张三

1

1

饭卡

2

李四

3

3

农行卡

3

王五

6

NULL

NULL

+------+--------+--------+------+-----------+

右外链接完整显示右边的表(card),左边的表如果符合条件就显示,不符合则补NULL。

SELECT*FROMpersonRIGHTJOINcardonperson.cardId=card.id;+------+--------+--------+------+-----------+

id

name

cardId

id

name

+------+--------+--------+------+-----------+

1

张三

1

1

饭卡

2

李四

3

3

农行卡

NULL

NULL

NULL

2

建行卡

NULL

NULL

NULL

4

工商卡

NULL

NULL

NULL

5

邮政卡

+------+--------+--------+------+-----------+

全外链接

完整显示两张表的全部数据。

--MySQL不支持这种语法的全外连接--SELECT*FROMpersonFULLJOINcardonperson.cardId=card.id;--出现错误:--ERROR4(42S22):Unknowncolumnperson.cardIdinonclause--MySQL全连接语法,使用UNION将两张表合并在一起。SELECT*FROMpersonLEFTJOINcardonperson.cardId=card.idUNIONSELECT*FROMpersonRIGHTJOINcardonperson.cardId=card.id;+------+--------+--------+------+-----------+

id

name

cardId

id

name

+------+--------+--------+------+-----------+

1

张三

1

1

饭卡

2

李四

3

3

农行卡

3

王五

6

NULL

NULL

NULL

NULL

NULL

2

建行卡

NULL

NULL

NULL

4

工商卡

NULL

NULL

NULL

5

邮政卡

+------+--------+--------+------+-----------+

全文到这里撒花完结~

1
查看完整版本: 20000字干货笔记,一天搞定MySQL