Mysql 表的增删查改(进阶)

1. 数据库约束

1.1 null 约束

创建表时可以指定某列不能为空

 只需在对应列的后面加上 not null

例:创建一个学生表,指定 id 不能为空

create table student (id int not null, name varchar(10));

创建成功后我们可以查看表结构

desc student;

Mysql 表的增删查改(进阶)_第1张图片

我们可以看见 id 对应的 null 列显示的 NO 表明插入数据时id不能为null

当我们尝试给id插入null值会提示报错信息

 

1.2 unique 唯一约束

创建表时,在某列的后面加上unique 可以指定该列的值不能重复

例:创建一个学生表,要求id的值不能重复

create table student(id int unique, name varchar(10));

我们查看表的结构,可以发现Key 下面对应id的行多了UNI

Mysql 表的增删查改(进阶)_第2张图片

 当我们向表中插入数据时,如果该数据的id在表中已有了则会插入失败

Mysql 表的增删查改(进阶)_第3张图片

注意:如果是修改表中原有的数据也要注意,修改id时不能与其他行重复 

1.3 default 约束

在创建表时可以在某列的后面加上 (default  默认值)
在插入数据时如果,没有给出该列的值,则会把这个默认值当作该列的值

例:创建一个学生表,指定 name 默认值为 " 佚名"

 create table student (id int, name varchar(10) default "佚名");

查看表可以发现,name 对应的default 变为了佚名 

Mysql 表的增删查改(进阶)_第4张图片

当我们插入数据时,没有给出name的值时则会自动给出 佚名,不过要注意如果给出null值的话,name则就为null不会被默认值替换

Mysql 表的增删查改(进阶)_第5张图片

 1.4 primary key 主键约束

 被primary key 约束的列,值不能为null且不能重复

例:

以id为主键创建学生表

create table student (id int primary key, name varchar(10));

查看表可以看到id对应的key列下多了PRI 

Mysql 表的增删查改(进阶)_第6张图片对于整数类型的主键,常配搭自增长auto_increment来使用。插入数据对应字段不给值或给null值时,使之为该列最大值+1(第一个数据时默认为1)

create table student (id int primary key auto_increment, name varchar(10));

Mysql 表的增删查改(进阶)_第7张图片

注意:如果我们删除第二条数据再插入id默认值将不会从2开始而是从3开始,如果要插入id为3的数据只能手动插入

Mysql 表的增删查改(进阶)_第8张图片

 作用:

  1. 加速数据检索:定义主键后,MySQL 会自动为主键列创建索引(下期会讲),这将大大加快基于主键列的数据检索速度。当使用主键进行查询时,数据库引擎会直接定位到相应的行,而不需要全表扫描。

  2. 用于建立关系:在关系型数据库中,主键通常用于建立不同表之间的关系。通过在其他表中引用包含主键的表,可以建立表与表之间的关联,实现数据的关联性查询和完整性约束。

 primary key 和 not null unique 的区别:

 以定义 列 id为例:

  1. id int PRIMARY KEY

    • 定义 id 列为主键,因此它将用于唯一标识表中的每一行数据。
    • 主键约束会自动将 id 列设定为 NOT NULL,因此 id 不允许包含 NULL 值。
    • 每个表只能有一个主键,因此在该表中 id 列是主键,而且是表中的唯一标识符。
  2. id int NOT NULL UNIQUE

    • 将 id 列定义为不允许为空且具有唯一性的列,即 id 列的值不能为 NULL,且表中的每个 id 值必须是唯一的。
    • 在这种情况下,id 列被定义为一个唯一键(UNIQUE),它可以确保列中的所有数值都是唯一的,但允许出现 NULL 值。

因此,在功能上,这两种定义方式都会实现 id 列的唯一性并禁止空值,但使用 PRIMARY KEY 会将 id 列明确地指定为表的主键,而使用 UNIQUE 索引则没有将 id 列明确指定为主键,也允许 NULL 值的存在。通常情况下,如果 id 列是表中的唯一标识符,更推荐使用 id int PRIMARY KEY 这种方式,因为它能够清晰地表明 id 列是主键。

1.5 foreign key 外键约束 

外键用于关联其他表的主键或唯一键

语法:

foreign key (列名) references 主表名(主键列名)

作用:

  1. 确保引用完整性: 外键约束可以确保引用完整性,即确保在一个表中引用另一个表中已经存在的数据。这意味着,如果在一个表中定义了外键约束,那么在插入或更新数据时,要求引用的数据必须存在于被引用的表中。

  2. 维护表之间的关联: 外键约束能够维护表与表之间的关联关系,确保相关表中的数据保持一致性。通过外键约束,一个表中的数据与另一个表中的数据进行关联,从而帮助数据库系统对数据之间的关系进行管理和维护。

  3. 防止孤儿记录: 外键约束可以防止产生孤儿记录,即一个表中引用另一个表中不存在的数据。这样可以确保数据的完整性,避免因为引用了不存在的数据而导致数据不一致的情况发生。

  4. 维护数据一致性: 通过外键约束,可以确保在相关表中的数据一致性,当父表中的数据发生变化时,可以通过外键约束来对子表中的数据进行级联操作,从而维护数据的一致性。

例:

创建一个班级表 令id为主键

 create table class_java (id int primary key auto_increment, name varchar(20));

创建一个学生表以班级id   class_id 为外键 关联班级表id

create table student (
id int primary key auto_increment,
name varchar(20),
class_id int,
foreign key (class_id) references class_java(id)
);

在班级表中插入数据

Mysql 表的增删查改(进阶)_第9张图片

在学生表中插入数据(class_id 只能是 class表中有的值,否则会报错)

Mysql 表的增删查改(进阶)_第10张图片

注意如果要删除数据,只能先删除子表的数据当父表中的某个引用值在子表中不存在时才能修改或删除该值,例如要把3该为4 只能先删除学生表中class_id 为3 的所有学生才能修改

3. 查询

3.1 查询插入

可以把一张表的查寻结果插入另一张表中,列的数据类型必须对应

例: 把上面学生表的id和姓名插入用户表 user中

创建用户表user

create table user(id int, name varchar(20));

插入:

insert into user select id, name from student;

Mysql 表的增删查改(进阶)_第11张图片

3.2 聚合查询

普通的查询方式不能进行行与行之间的运算,这时候就需要聚合查询 

3.2.1 聚合函数
函数 说明
COUNT([DISTINCT] expr) 返回查询到的数据的 数量
SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义
AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义
MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义
MIN([DISTINCT] expr) 返回查询到的数据的 最小值,不是数字没有意义

例:

统计学生表学生的数量:

select count(*) from student;

Mysql 表的增删查改(进阶)_第12张图片

 统计学生表学生id的总和:

select sum(id) from student;

Mysql 表的增删查改(进阶)_第13张图片

 

3.2.2 group by  

select 中使用group by 可以对指定列进行分组查询 

使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中,否则将只输出每组的第一个数据

例:创建职员表,有id(主键)、name(姓名)、role(角色)、salary(薪水)

 

create table emp(
id int primary key auto_increment,
name varchar(20) not null,
role varchar(20) not null,
salary numeric(11,2)
);

插入数据

Mysql 表的增删查改(进阶)_第14张图片

查询每个职位的最高工资、最低工资和平均工资

select role, max(salary), min(salary), avg(salary) from emp group by role;

Mysql 表的增删查改(进阶)_第15张图片

3.2.3 having 

where 只能对分组前的数据进行筛选,要对分组后的结果进行筛选时要用having 

例:

 显示平均工资低于25000的职位和它的平均工资 

select role, avg(salary) from emp group by role having avg(salary) > 25000;

Mysql 表的增删查改(进阶)_第16张图片

3.3 联合查询

实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积

初始化测试数据:

上面我们有了学生表和班级表,我们再创建一个课程表与分数表:

 创建课程表:

create table course(id int primary key auto_increment, name varchar(20));

创建分数表:

create table score(
id int primary key auto_increment, 
score int, 
student_id int, 
course_id int,
foreign key (student_id) references student(id),
foreign key (course_id) references course(id)
);

插入一些数据:

insert into course(name) values
    -> ("JavaSE语法"),
    -> ("数据结构"),
    -> ("MySQL"),
    -> ("JavaEE");

 

insert into score(score, student_id, course_id) values
-- 小明
(70, 2001, 1), (98, 2001, 3), (33, 2001, 4),
-- 小芳
(60, 2002, 1), (59, 2002, 2),
-- 小李
(33, 2003, 1),(68, 2003, 3),(99, 2003, 4),
-- 小芬
(67, 2004, 1),(23, 2004, 2),(56, 2004, 3),
-- 小刚
(81, 2005, 1),(37, 2005, 4),
-- 小华
(56, 2006, 2),(43, 2006, 3),(79, 2006, 4);
3.3.1 内连接

 语法:

select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;

例:

查询小芬同学的课程id 和 对应成绩

select score.course_id, score.score from student join score on student.name = "小芬" and score.student_id = student.id;

Mysql 表的增删查改(进阶)_第17张图片

 查询每个同学的 姓名 和每个课程的 名称 以及对应的 得分

select student.name, course.name, score.score from 
student, course, score where
score.student_id = student.id and
score.course_id = course.id;

Mysql 表的增删查改(进阶)_第18张图片

 

3.2.2 外连接

内连接只能显示对应行中有数据的行

外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。

语法:

-- 左外连接,表1完全显示
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 字段 from 表名1 right join 表名2 on 连接条件;

例:查询所有同学的成绩,及同学的个人信息,如果该同学没有成绩,也需要显示

 我们再插入一个同学:

 按要求查询成绩:

select student.id, student.name, course.name, score.score
from student 
left join score on
student.id = score.student_id
left join course on
course.id = score.course_id;

Mysql 表的增删查改(进阶)_第19张图片

3.2.3 自连接 

自连接是指在同一张表连接自身进行查询
查询 avaSE语法 成绩大于 JavaEE 成绩的同学信息以及这两科的成绩

select student.id, student.name, c1.name, s1.score, c2.name, s2.score
from student
join score as s1 on student.id = s1.student_id
join course as c1 on c1.id = s1.course_id and c1.name = "JavaEE"
join score as s2 on student.id = s2.student_id and s1.score < s2.score
join course as c2 on c2.id = s2.course_id and c2.name = "JavaSE语法";

Mysql 表的增删查改(进阶)_第20张图片

注意:自连接时要给列取别名 来区分两列 

 3.2.4 子查询

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

单子查询:

例:查询与小明同班的同学 

select * from student where class_id = (
select class_id from student where name = "小明");

 Mysql 表的增删查改(进阶)_第21张图片

 多子查询:

1. (not) in 

查询JavaEE或MySQL的成绩

select * from score where course_id in (
select id from course where name = "JavaEE" or name = "MySQL");

Mysql 表的增删查改(进阶)_第22张图片

加上not则是查 avaEE,MySQL以外的成绩

 2. (not) exists

select * from score where exists (
select id from course where (name = "JavaEE" or name = "MySQL") 
and score.course_id = course.id);

Mysql 表的增删查改(进阶)_第23张图片

 

你可能感兴趣的:(mysql,数据库)