约束
1.null约束
创建表时,可以指定某列不为空,如果插入的数据为空那就会报错,如下例子:
create table 表名(列名1 列名1类型 not null, 列名2 列名2类型, ......);

2.unique唯一约束
创建表时某列使用unique时,插入数据时使用了unique约束的列就必须唯一,如果插入相同的数据则会报错;
create table 表名(列名1 列名1类型 unique, 列名2 列名2类型, ......);

3.default默认值约束
如果不对default进行命名默认为null,defalut类似于描述信息,下面用例子更好解释其用意
create table 表名(列名1 列名1类型, 列名2 列名2类型 default '列名2的含义', ......);

上一章节中提到的 查看表结构(desc 表名;) ,以及desc降序,这两个desc分别指的是describe描述、descend降序;
4.primary key主键约束
在一个表中只能有一个主键约束,它的作用是身份标识。例如:每个人只有一个身份证号,所以当查询这个身份证号是就知道这个人是谁;又例如:在学校可以通过学号来查询对应的姓名等信息;
create table 表名(列名1 列名1类型 primary key, 列名2 列名2类型, ......);

对于主键是整数类型的,我们还可以通过auto_increment自增主键(从1开始往上增加);
create table 表名(列名1 列名1类型 primary key auto_increment, 列名2 列名2类型);

5.foreign key外键约束
外键约束描述的是两表之间的关联关系,外键是通过父表约束子表 。例如:多个学生选课,那么选择的课程必须是学校中存在的课程,如果某个学生想选择了化学,而学校根本就没有开设这门课程,那么学生就无法选择化学这门学科。同理就是如果子表中超过了父表的限制就会报错无法插入成功, 想要将两个表创建联系两个表就必须都存在主键,通过主键键两表联系起来(通过身份标识来对应该门课程);
create table 子表名 values(列名1 列名1类型 (主键), 列名2 列名2类型, 列名3 列名3类型, foreign key(列名3) references 父表名(父表主键列名));//大概可以这样写,也可以变换顺序


对于使用外键约束后,如果想要修改父表的值是不可以的;同样如果约束一直存在,就不可以先删除父表 ;注:指定外键约束时,要求父表中被关联的列必须是主键约束或者唯一约束;


6.check约束
create table 表名(列名1 列名1类型, check(列名1 = '某个值' or 列名1 = '某个值' or ......), 列名2 列名2类型, ......);
check约束是将该选择只限于某几个,当不是限制内的选择时,程序会报错,如下图

表的设计
1.一对一
一对一就是像一个学生只能一个账号,一个账号只能被一个学生使用;
student(student_Id varchar(20), name varchar(20), account_Id varchar(20));
account(account_Id varchar(20), username varchar(20), password varchar(20));
2. 一对多
一对多就像一个班级里可以包含多个学生,但是一个学生只能在一个班级中;而mysql中不支持数组所以只能一个一个添加;
class(id int, name varchar(20));
student(id int, name varchar(20), class_Id int);
3.多对多
多对多就像一个学生可以选择多门学科,一门学科也可以被多个学生选择;
student(id int, name varchar(20));
course(id int, course varchar(20));
4.没关系
以上三种都是相关联的两个表,没有关联的两个表就是没关系;
查询
1.聚合查询
聚合查询是针对行和行之间进行的运算;而表达式查询时针对列和列
1.1聚合函数
- count()【更好理解就是一个班"总共"多少人】
1.count(*):对总行进行计数,也存在空计算(也就是一行全为空也包含在内)
2.count(列名):对该列进行去空值计数
3.count(distinct 列名):对该列即去除空值又去除重复计数
注意: count和()之间有空格时会报错的。
- sum()【把一列的若干行求和计算】
1.sum(列名)进行该列求和。
2.sum(字符串):如果计算该列为字符串类型,则需要先将字符串转成double类型在进行计算;
3.sum(表达式):如果计算该列是一个表达式,内部操作就是先将表达式计算得到一个临时表,然后再对临时表进行行与行之间的运算;当然直接一步就可以求出来,只是为了证明聚合函数是一个行与行之间的运算。
- avg()【求满足列的行平均值】
- max()
- min()
avg求平均值、max求最大值、min求最小值 道理同sum求和的原理相同,就不再重复说明了

1.2group by分组
gruop by是将多组数据按某个条件分成几组多个数据,例如:工作职位有老板、程序员、项目经理等,这三类下面有很多对应职位的人,如果算平均工作,每类人所拿到的工资差距不一样,进行对比就没有了意义,所以就可以通过group by进行分组,再对每类人进行求平均值比较才有了意义;
**group by (列名)一般写到末尾,如果还有where条件的话where一般在group by前面;**下面求平均工资就用到了分组+聚合


1.3having
having是对group by分组以后的表进行条件筛选,这时就不能使用where语句了。所以having都是配合着group by一起使用的,而且两个都存在是having语句就在末尾了;
平均工资低于8000的部门;

2.联合查询/多表查询
1.内连接
在实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询就是对多张表进行笛卡尔积,该操作需要将两张表出现的情况全部穷举一遍,如果每个表中存在的数据都很多,那笛卡尔积后将会更多;

-
1.确定两表所有数据笛卡尔积
select * from student, course;
-
2.删除无意义的数据,找两个表中相关联的(进行筛选)
select * from student, course where student.id = course.student_id;
-
找所需要的列(精简数据结果)
select student.name, course.course from student.course where student.id = course.student_id;
-
改名字(【旧名 as 新名】,其中as可以省略不写,但是为了更好都更好读代码建议写上)
select student.name as studentName, course.course as courseCourse from ......;
内连接也可以通过【select 字段名 from (inner)join 分两张表 on 条件】,其中where可以看作on
select * from join student,course on student.id = course.student_id;
2.外连接
如果两个表之间存在对应关系,那么内连接和外连接结果一致,如果不存在就会出现差异,如下图:

- 左外连接
想要查询左外连接可以通过【select 字段名 from 表1 left join 表2 on条件】

- 右外连接
想要查询右外连接可以通过【select 字段名 from 表1 right join 表2 on条件】

- 全外连接
由于mysql不支持全外连接,所以了解即可


3.自链接
自链接就是自己和自己笛卡尔积,可以把行关系转成列关系,如课程1的分数>课程3的分数;就是要注意一个表中不能有重名的表名(需要改名字),找表1中的id属性可以【表名.属性】表现。
select ... from 表1 as 新名1,表1 as 新名2 where 条件
select ... from 表1 as 新名1 join 表1 as 新名2 on 条件

4.子查询
子查询是指嵌入其他sql语句中的select语句,也叫嵌套查询

例如:正常情况下查询'不想毕业'同学的同班同学要通过两步查询
第一步:查询'不想毕业'同学所在班级
第二步:直到该班级后,查询该班级的学生不包含'不想毕业'
select class_id from where name = '不想毕业';
select name from student where name != '不想毕业' and class_id = 1;
-
单行子查询(就是将第一步代替1)
select ... from 表1 where 字段1 = (select ... from ...);
select name,class_id from student where class_id = (select class_id from student where name = '不想毕业') and name != '不想毕业';
使用单行子查询时,必须满足返回的结果只有一个,多个就不可以;
- 多行子查询(in /exist + ( 第一步代替) )
如果返回多个记录,我们就可以通过in来接收
select ... from 表1 where 字段1 in (select ... from ...);
select ... from 表1 where exists (select ... from ... where 条件);
select score.student_id, score.course_id, score.score from score where score.course_id in(select id from course where name = '语文' or name = '英文');
5.合并查询 (union)
把多个sql查询的结果合并在一起,合并两个sql的结果集,需要进行匹配(列的个数以及类型要一致才可以合并),最终结果显示前面表的类型名,而且如果两个表中存在相同属性数据,则会去除重复行,当然如果不想去除可以使用union all;
select 字段名 from 表1 union select 字段名 from 表2;
重点内容
- 约束

- 表的设计

- 查询

SQL查询中各个关键字的执行先后顺序: from > on> join > where > group by > with > having > select > distinct > order by > limit
小知识:如果使用注释,可以通过#/(--+空格) 进行注解;