本节目标
MySQL表的增删改查(进阶):
1. 数据库约束
2. 表的设计
3. 新增
4. 查询
1. 数据库约束
数据库自动对数据的合法性进行校验的一系列机制,避免数据库被插入/修改一些非法数据。
约束类型(constraint)
not null - 指示某列不能存储 null 值
创建表时,指定某列不为空。
unique - 保证某列的每行必须有唯一的值
指定某列为唯一的,不重复的
unique约束会让后续插入/修改的时候,都会先触发一次查询操作,导致执行效率降低
default - 规定没有给列赋值时的默认值
指定插入数据时,某列为空,默认值为(具体填写)
primary key - not null 和 unique 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录
一张表中只能有一个primary key(相当于一个全局变量),经常使用int/bigint
虽然只能有一个主键,但主键可以不是只有一列,多个列共同构成一个主键(联合主键)
对于带主键的表,每一次插入/修改也会先查询
对于整数类型的主键,常配搭自增长auto_increment来使用。插入数据对应字段不给值时,使用最大值+1
MySQL会给primary key和unique提供索引,加快搜索效率
foreign key - 保证一个表中的数据匹配另一个表中的值的参照完整性
表名1 (列名1,列名2,... foreign key (列名1) references 表名2 (列名));
描述了两个表的列之间的关联关系,其他的列不受影响
针对父表的修改/删除操作,如果被操作的值已经子表利用,则操作失败
外键约束要始终保持,子表中的数据在对应的父表的列中要保存
指定外键约束时,要求父表中被关联到的列,是主键或unique
想删除约束,得先删除子表的记录。
父表中的数据:
子表的插入操作:
父表的删除:
check - 保证列中的值符合指定的条件。对于MySQL数据库,对check子句进行分析,但是忽略 check子句
2. 表的设计
三大范式:
1. 一对一:学生与账户
student(studentId int,name varchar(20));
account (cacountId int,username varchar(20),passward varchar(20),studentId int);
2. 一对多:学生与班级
class(id int,name varchar(20));
student(id int,name varchar(20),classId int);
3. 多对多:学生与课程
student (id int,name varchar(20));
course (id int,name varchar(20));
studnet-course (studentId int,courseId int); //借助关联表,表示多对多关系
3. 新增数据
查询可以搭配插入使用,把查询语句的查询结果作为插入值
insert into 表名1 select *from 表名2;
要求查询出来的结果集合,列数/类和插入的表匹配
4. 查询
4.1 聚合查询
表达式查询--列与列计算 聚合查询--行与行计算
聚合函数:
count([distinct] expr...) | 返回查询到的数据的数量 |
sum([distinct] expr...) | 返回查询到的数据的总和, 不是数字没有意义 |
avg([distinct] expr...) | 返回查询到的数据的平均值, 不是数字没有意义 |
max([distinct] expr...) | 返回查询到的数据的最大值, 不是数字没有意义 |
min([distinct] expr...) | 返回查询到的数据的最小值, 不是数字没有意义 |
算术运算
group by 子句:
针对指定的列进行分组,把这一列中值相同的行分到一组中
针对这些分组分别使用聚合函数,如果不使用聚合函数,此时的结果是查询出来的每一组中的某个代表数据
select 列名1,函数(列名2,...) from 表名 group by 列名1,列名3;
having:
group by 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用where 语句,而需要用 having
分组前设置的条件:直接使用where子句,一般写在group by子句之前
分组后设置的条件:使用having描述条件,一般写在group by子句之前
4.2 联合查询/多表查询
4.2.1 笛卡尔积的工作过程
笛卡尔积是把所有可能的情况都穷举一遍,通过排序组合的方式得到一个更大的表,包含一些合法数据和非法数据。进行多表查询时,就是把有意义的数据筛选出来,把无意义的数据过滤掉。
笛卡尔积的行数,是这两个表的行数相乘;笛卡尔积的列数,是这两个列的列数相加
1)把这两个表,进行笛卡尔积
select *from student,score;
2)加上筛选条件,筛选出有效数据
3)结合需求,进一步添加条件,针对结果进行筛选
4)针对查询到的列进行精简,只保留需求中关心的列
student 表
course表
score表
select student.name,score.score from student,score,course where student.name = "小赵" and student.id = score.studnetId;
4.2.2 内连接
select 列名 from 表名1 别名1 [inner] join 表名2 别名2 on 连接条件 and 其他条件;
select 列名 from 表名1 别名1 ,表名2 别名2 where 连接条件 and 其他条件;
例如查找所有同学的成绩:
select student.name,course.name,score.score from student,score,course where student.id = score.studnetId and course.id = score.courseId order by student.name;
4.2.3 外连接
外连接分为左外连接和右外连接
左外连接:left join
右外连接:right join
4.2.4 自连接
自连接是指在同一张表连接自身进行查询
select ... from 表名1,表名1 where 条件;
select ... from 表名1 join 表名1 on 条件;
4.2.5 子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询
单行查询:返回一行的记录
例如查询小李同班同学
多行查询:返回多行记录
[not] in 关键字
[not] exist 关键字
4.2.6 合并查询
把多个SQL语句查询的结果集和合并到一起
合并的两个SQL的结果集的列要匹配(列的个数,类型(类名不需要一致,结果与第一个表保持一致))
union 该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
合并的时候,自动去重。不想去重可以使用union all
union all 允许把两个不同的表的查询结果放到一起