表的增删查改(进阶)—MySQL

1.数据库约束

约束:按照一定的条件进行规范的做事,表定义的时候,某些字段保存的数据,需要按照一定的约束条件

1.1 null约束

(1)字段null:该字段可以为空
(2)字段not null:该字段不允许为空(如果插入数据的时候没插入或者插入null都会报错)
(3)不指定默认是允许为空

--非空约束
drop table if exists student;
create table student(
    id int not null,
    name varchar(20),
    sex bit,
    resume text,
    amount decimal(11,2),
    birthday datetime
);
insert into student(id,name) values (1,'张三');
-- 报错
insert into student(name) values ('张三');

在这里插入图片描述

1.2 unique:唯一约束

表示某个字段,不能重复,null不进行unique唯一性校验,实际可以使用多个字段来建立unique唯一约束(该字段插入相同的值会报错)

-- 唯一约束
drop table if exists student;
create table student(
    id int not null,
    name varchar(20) unique,
    sex bit,
    resume text,
    amount decimal(11,2),
    birthday datetime
);
insert into student(id,name) values (1,'张三');
-- 报错,姓名不能重复
insert into student(id,name) values (2,'张三');

在这里插入图片描述

1.3 default:默认值约束

(1)某个字段设置了default及默认值,插入的时候,该列不插入,就会插入默认值
(2)显示的插入数据,即使是null,默认值也不会生效

-- 默认值约束
drop table if exists student;
create table student(
    id int not null ,
    name varchar(20) default 'unkown',
    sex bit,
    resume text,
    amount decimal(11,2),
    birthday datetime
);
insert into student(id,name) values (1,'张三');
-- id 为2的学生姓名默认插入unknown
insert into student(id) values (2);

在这里插入图片描述

1.4 primary key:主键约束(非空且唯一)

(1)primary key = not null
(2)主键一般就用于某张表,标识唯一的一条数据,主键约束也可以使用多个字段,也叫复合主键
(3)仅仅unique约束的字段,还可以保存多条null的数据,也不能标识唯一的数据
(4)主键字段,不插入,或者是插入重复,就会报错

-- 主键约束
drop table if exists student;
create table student(
    id int primary key,
    name varchar(20) default 'unkown',
    sex bit,
    resume text,
    amount decimal(11,2),
    birthday datetime
);
insert into student(id,name) values (1,'张三');
-- 重复报错
insert into student(id,name) values (1,'李四');
-- 不插入也报错
insert into student(name) values ('李四');

在这里插入图片描述
(5)简单看,一张表,一般都需要设计一个主键
(6)如果使用整形主键,还可以结合auto_increment(这个是MySQL的关键字,不是标椎sql),表示从1开始,++自增

drop table if exists student;
create table student(
    id int primary key auto_increment,
    name varchar(20) default 'unkown',
    sex bit,
    resume text,
    amount decimal(11,2),
    birthday datetime
);
insert into student(id,name) values (1,'张三');
insert into student(name) values ('李四');
insert into student(name) values ('王五');

在这里插入图片描述

1.5 foreign key:外键约束

(1)用于设计表和表之间的关系
(2)表1(主表:主键)——表2(从表:外键):建立表1和表2,一对多或一对一的关系

-- 学生表(主表)
drop table if exists student;
create table student(
    -- 学生表主键
    id int primary key auto_increment,
    name varchar(20) not null
);
-- 中间表:学生考试成绩表
drop table if exists exam_score;
create table exam_score(
    -- 学生考试成绩表主键
    id int primary key auto_increment,
    -- 学生表的主键作为中间表的外键
    student_id int,
    -- 建立主外键关系
    foreign key(student_id) references student(id),
);

1.6 check约束(MySQL没有实现)

drop table if exists student;
create table student (
   id int,
   name varchar(20),
   sex varchar(1),
   -- sex只能是男和女,插入其他的就会报错
   check (sex ='男' or sex='女')
);

2.表的设计

数据库的表设计就是建立一种对象模型

2.1数据库建立表关系

(1)语法上只有一中写法
在这里插入图片描述
主表的主键关联从表的外键(实际上建立外键,不一定要使用主键来关联)
(2)写法
在这里插入图片描述

2.2一对一关系

在这里插入图片描述
(1)从实现上看,一张表也可以实现,但是效率不高(比如:比较频繁的获取人的姓名而不需要获取身份信息)
(2)设计两张表的目的:解耦:模型之间的解耦;效率:不经常使用的数据单独存储,效率比较高

2.3一对多关系

在这里插入图片描述
一对多是有方向的,包含:
(1)班级到学生:一对多,一个班级多个学生
(2)学生到班级:一对一,一个学生一个班级

2.4多对多关系

(1)表设计的时候:两张主表建立多对多关系的时候,主表中没有外键体现;使用一张单独的中间表来表示两张主表的多对多关系,设计两个外键分别关联两张主表的主键,当然也可以设计一些其他的字段
(2)表结构上:只有两个一对多关系,数据上体现出两个一对多以及逻辑上的多对多关系

-- 学生表(主表)
drop table if exists student;
create table student(
    -- 学生表主键
    id int primary key auto_increment,
    name varchar(20) not null
);
-- 课程表(主表)
drop table if exists course;
create table course(
    -- 课程表主键
    id int primary key auto_increment,
    name varchar(20) not null
);
-- 中间表(从表):学生考试成绩表
drop table if exists exam_score;
create table exam_score(
    -- 学生考试成绩表主键
    id int primary key auto_increment,
    -- 学生表的主键作为中间表的外键
    student_id int,
    -- 课程表的主键作为中间表的外键
    course_id int,
    -- 建立主外键关系
    foreign key(student_id) references student(id),
    foreign key(course_id) references course(id)
);
-- 插入数据
insert into student values(1,'张三');
insert into student values(2,'李四');
insert into student values(3,'王五');
insert into course values(1,'语文');
insert into course values(2,'数学');
insert into exam_score(student_id,course_id) values(1,1);
insert into exam_score(student_id,course_id) values(1,2);
insert into exam_score(student_id,course_id) values(2,1);
insert into exam_score(student_id,course_id) values(2,2);
insert into exam_score(student_id,course_id) values(3,1);
insert into exam_score(student_id,course_id) values(3,2);

在这里插入图片描述
在这里插入图片描述

(3)关系
在这里插入图片描述

3.插入数据

语法:insert into 表名(要插入的表名) select 要查询的字段 from 表名(要查询的表名) where …order by … limit;

3.1使用场景

(1)复制表
(2)提前准备一些统计的数据

-- 数据准备
-- 学生表
drop table if exists student;
create table student(
    id int primary key auto_increment,
    name varchar(20) not null
);
insert into student values(1,'张三');
insert into student values(2,'李四');
insert into student values(3,'王五');
-- 课程表
drop table if exists course;
create table course(
    id int primary key auto_increment,
    name varchar(20) not null
);
insert into course values(1,'语文');
insert into course values(2,'数学');
-- 学生考试成绩表
drop table if exists exam_score;
create table exam_score(
    id int primary key auto_increment,
    score decimal(4,1),
    student_id int,
    course_id int,
    foreign key(student_id) references student(id),
    foreign key(course_id) references course(id)
);
insert into exam_score(student_id,course_id,score) values(1,1,100);
insert into exam_score(student_id,course_id,score) values(1,2,110);
insert into exam_score(student_id,course_id,score) values(2,1,89);
insert into exam_score(student_id,course_id,score) values(2,2,99);
insert into exam_score(student_id,course_id,score) values(3,1,121);
insert into exam_score(student_id,course_id,score) values(3,2,111);
-- 学生成绩总表
drop table if exists score_total;
create table score_total(
    id int primary key auto_increment,
    score decimal(4,1),
    -- 学生信息
    student_id int,
    student_name varchar(20),
    -- 课程信息
    course_id int,
    course_name varchar(20)
);
-- 插入数据
insert into score_total(
    score,
    student_id,
    student_name,
    course_id,
    course_name
)select
    score,
    student_id,
    null,
    course_id,
    null
from exam_score where id between 2 and 5;

结果:
在这里插入图片描述

4.查询数据

4.1聚合查询

查询返回结果集合,再进行聚合

4.1.1聚合函数

会将结果集所有数据进行聚合,合并为一行,使用分组操作也可以合并为多行
(1)sum(某个字段):求和
(2)avg(某个字段):求平均值
(3)max(某个字段):求最大值
(4)min(某个字段):求最小值
(5)count():获取整个结果集的行数(数据数量)

count(某个字段)=count(*)=count(常量值)
(常量值可以是0-n的任意数字)

-- 数据准备
create table exam_result (
 id int,
 name varchar(20),
 chinese decimal(3,1),
 math decimal(3,1),
 english decimal(3,1)
);
insert into exam_result (id,name, chinese, math, english) values
    (1,'唐三藏', 67, 98, 56),
    (2,'孙悟空', 87.5, 78, 77),
    (3,'猪悟能', 88, 98.5, 90),
    (4,'曹孟德', 82, 84, 67),
    (5,'刘玄德', 55.5, 85, 45),
    (6,'孙权', 70, 73, 78.5),
    (7,'宋公明', 75, 65, 30);

select sum(math),avg(math),max(math),min(math) from exam_result;
select count(0) from exam_result;

在这里插入图片描述
在这里插入图片描述

4.1.2 group by(分组)

语法:select 查询字段 from 表名 where 条件 group by 分组字段1,分组字段2;

--  数据准备
-- 学生表
drop table if exists student;
create table student(
    id int primary key auto_increment,
    name varchar(20) not null
);
insert into student values(1,'张三');
insert into student values(2,'李四');
insert into student values(3,'王五');
-- 课程表
drop table if exists course;
create table course(
    id int primary key auto_increment,
    name varchar(20) not null
);
insert into course values(1,'语文');
insert into course values(2,'数学');
-- 学生考试成绩表
drop table if exists exam_score;
create table exam_score(
    id int primary key auto_increment,
    score decimal(4,1),
    student_id int,
    course_id int,
    foreign key(student_id) references student(id),
    foreign key(course_id) references course(id)
);
insert into exam_score(student_id,course_id,score) values(1,1,100);
insert into exam_score(student_id,course_id,score) values(1,2,110);
insert into exam_score(student_id,course_id,score) values(2,1,89);
insert into exam_score(student_id,course_id,score) values(2,2,99);
insert into exam_score(student_id,course_id,score) values(3,1,121);
insert into exam_score(student_id,course_id,score) values(3,2,111);
select student_id,sum(score),count(0) from exam_score group by student_id;

在这里插入图片描述

select * from exam_score group by student_id;

在这里插入图片描述

(1)执行过程:
①执行查询操作
②按分组字段进行分组
③把三个分组每个组里面的多条数据进行合并
(2)分组查询操作要求:
①查询字段必须是分组字段
②如果分组会造成聚合,非分组字段必须写在聚合函数中
③如果分组不会造成聚合,非分组字段可以直接写
(3)多个分组字段:常用于多表查询

select student_id,course_id,sum(score) from exam_score group by student_id,course_id;

在这里插入图片描述

4.1.3having(分组后的过滤条件)

语法:select 查询字段 from 表名 where 条件 group by 分组字段 having 分组后条件;

(1)执行过程:
①执行查询操作
②分组
③分组条件过滤
(2)having是在分组后执行,having中的字段也需要满足分组查询操作的三个条件
(3)group by+having 经常用来查询重复数据

select student_id,course_id,sum(score) from exam_score group by student_id,course_id having count(0) > 1;

在这里插入图片描述

4.2联合查询(多表查询,复合查询)

(1)多表联合查询操作使用字段的时候必须使用表名.字段名
(2)联合查询就是将单纯的笛卡尔积返回的结果进行过滤

-- 数据准备
drop database test;
create database test character set utf8mb4;
use test;
-- 学生表
drop table if exists student;
create table student(
    id int primary key auto_increment,
    name varchar(20) not null,
    classes_id int
);
insert into student(name,classes_id) values('张三',1);
insert into student(name,classes_id) values('李四',1);
insert into student(name,classes_id) values('王五',2);
-- 班级表
drop table if exists classes;
create table classes(
    id int primary key auto_increment,
    name varchar(20)
); 
insert into classes(name) values('数学系一班');
insert into classes(name) values('计算机系一班');
-- 课程表
drop table if exists course;
create table course(
    id int primary key auto_increment,
    name varchar(20) not null
);
insert into course values(1,'语文');
insert into course values(2,'数学');
-- 学生考试成绩表
drop table if exists exam_score;
create table exam_score(
    id int primary key auto_increment,
    score decimal(4,1),
    student_id int,
    course_id int,
    foreign key(student_id) references student(id),
    foreign key(course_id) references course(id)
);
insert into exam_score(student_id,course_id,score) values(1,1,100);
insert into exam_score(student_id,course_id,score) values(1,2,110);
insert into exam_score(student_id,course_id,score) values(2,1,89);
insert into exam_score(student_id,course_id,score) values(2,2,99);
insert into exam_score(student_id,course_id,score) values(1,1,77);
insert into exam_score(student_id,course_id,score) values(1,2,88);
insert into exam_score(student_id,course_id,score) values(2,1,133);
insert into exam_score(student_id,course_id,score) values(2,2,109);
insert into exam_score(student_id,course_id,score) values(3,1,121);
insert into exam_score(student_id,course_id,score) values(3,2,111);

表关系:
在这里插入图片描述

4.2.1两个表的笛卡尔积

语法:select 表名.查询的字段 from 表1,表2;

(1)执行过程:(先遍历第一张表还是先遍历第二张表都可以)
①遍历第一张表的数据
②第一张表的每条数据和第二张表的每条数据相关联
③遍历第二张表的数据
(2)笛卡尔积的结果:两张表的每条数据相连接,产生一个结果集(虚拟表)
(3)结果集的行数=第一张表的行数*第二张表的行数
(4)单纯的笛卡尔积返回的数据没有什么意义

select * from student,classes;

在这里插入图片描述

4.2.2内连接

语法:
select 查询字段 from 表1,表2 where 连接条件 and 其他条件
select 查询字段 from 表1 [inner] join 表2 on 连接条件 where 其他条件

(1)内连接中连接条件和其他条件没有什么区别
(2)执行过程
①使用联合查询:先用笛卡尔积,再进行where条件过滤

select * from student,classes 
    where student.classes_id = classes.id;

在这里插入图片描述
②使用别名简化代码

select * from student as s,classes as c
    where s.classes_id = c.id;

③将 * 改为所有要查询的字段(建议的写法)

select 
    s.id s_id,
    s.name s_name,
    c.id c_id,
    c.name c_name 
from student s,classes c
    where s.classes_id = c.id;

在这里插入图片描述
(3)内连接必须满足连接条件和其他条件才会返回
(4)关联两张以上的表

select 
    s.id s_id,
    s.name s_name,
    c.id c_id,
    c.name c_name,
    e.score,
    e.course_id
from student s,classes c,exam_score e
    where s.classes_id = c.id
    and s.id = e.student_id;

(5)查询课程id=1的所有班级的平均分

select
    c.id c_id,
    c.name c_name,
    avg(e.score)
from student s, classes c,exam_score e
    where s.classes_id = c.id
    and s.id = e.student_id
    and e.course_id = 1
group by c.id;

在这里插入图片描述
(6)查询“语文”课程的所有班级的平均分

select
    c.id c_id,
    c.name c_name,
    cou.name cou_name,
    avg(e.score)
from student s,classes c,exam_score e,course cou
    where s.classes_id = c.id
    and s.id = e.student_id
    and e.course_id = cou.id
    and cou.name = '语文'
group by c.id;

在这里插入图片描述
(7)查询所有课程的所有班级的平均分

select
    c.id c_id,
    c.name c_name,
    cou.name cou_name,
    avg(e.score)
from student s,classes c,exam_score e,course cou
    where s.classes_id = c.id
    and s.id = e.student_id
    and e.course_id = cou.id
group by c.id,cou.id;
-- join on 写法
select
    c.id c_id,
    c.name c_name,
    cou.name cou_name,
    avg(e.score)
from student s
    join classes c on s.classes_id = c.id
    join exam_score e on s.id = e.student_id
    join course cou on e.course_id = cou.id
group by c.id,cou.id;

在这里插入图片描述

4.2.3外连接

语法:
左外连接:select 查询字段 from 左表 left join 右表 on 连接条件 where 其他条件
右外连接:select 查询字段 from 左表 right join 右表 on 连接条件 where 其他条件

(1)左外连接的左表和右外连接的右表是外表

-- 班级表作为外表,即使班级中没有数据,也可以显示,但是内连接就不可以显示
-- 插入数据
insert into classes(name) values('会计系一班');
select 
    s.id s_id,
    s.name s_name,
    c.id c_id,
    c.name c_name,
    s.classes_id
from student s
    right join classes c 
    on s.classes_id = c.id;

在这里插入图片描述
(2)外连接满足连接条件和其他条件或者满足其他条件但是外表存在,即使不满足连接条件也可以返回

4.2.4内连接和外连接的区别

(1)内连接必须满足连接条件和其他条件才会返回
(2)外连接满足连接条件和其他条件或者满足其他条件但是外表存在,即使不满足连接条件也可以返回

4.2.5自连接

(1)表自己连接自己
(2)常用于自身多行数据,同一个字段进行比较操作

-- 查询课程id = 1成绩大于课程id = 2
select
    *
from exam_score e1,exam_score e2
    where e1.student_id = e2.student_id
    and e1.course_id = 1
    and e2.course_id = 2
    and e1.score > e2. score;
-- 查询语文成绩大于数学成绩
select
    e1.student_id,
    e1.score '语文成绩',
    e2.score '数学成绩'
from exam_score e1,exam_score e2,course c1,course c2
    where e1.student_id = e2.student_id
    and c1.name = '语文'
    and c2.name = '数学'
    and e1.score > e2. score;

4.2.6子查询

(1)子查询返回一行数据,可以当做常量

语法:
– 单行子查询
select … from 表1 where 字段1 = (select … from …);

-- 查询张三同学的同班同学
select
    *
from student
where classes_id = (
    select classes_id from student where name = '张三'
);

在这里插入图片描述

(2)[not] in

语法:
select … from 表1 where 字段1 in (select … from …);

-- 查询张三和李四的成绩
select
    *
from exam_score
where student_id in(
    select id from student where name = '张三' or name = '李四'
);
-- 插入数据
insert into exam_score(score,student_id,course_id)
    values (110,1,2),(89,2,1);
-- 查询重复的分数
select
    *
from exam_score
where (score,student_id,course_id)
in(select 
    score,student_id,course_id
from exam_score
group by score,student_id,course_id
having count(0) > 1
);

在这里插入图片描述
在这里插入图片描述

(3)[not] exists

语法:select … from 表1 where exists (select … from … where 条件);

-- 查询张三和李四的成绩
select
    *
from exam_score e
where exists(
    select 1 from student s 
    where e.student_id = s.id
    and (s.name = '张三' or s.name = '李四')
);

(4) 临时表:from子句中的子查询

语法:select … from 表1, (select … from …) as tmp where 条件;

-- 查询平均分数比“数学系一班”高的班级
-- 查平均分
select 
    avg(e.score)
from exam_score e,student s,classes c
    where e.student_id = s.id
    and s.classes_id = c.id
    and c.name = '数学系一班';
select 
    es.*
from exam_score es,
    (select 
    avg(e.score) avg_score
    from exam_score e,student s,classes c
    where e.student_id = s.id
    and s.classes_id = c.id
    and c.name = '数学系一班')tmp
where es.score > tmp.avg_score;

在这里插入图片描述

4.2.7合并查询

(1)union all:取两个结果集的并集

select
    *
    from course 
    where id <= 2
    union 
    select * from course where name = '语文';

在这里插入图片描述

(2)union:取两个结果集的并集,并去重(按照结果集所有查询字段去重)

select
    *
    from course 
    where id <= 2
    union all
    select * from course where name = '语文';

在这里插入图片描述
(3)单表的结果集取并集其实是可以使用or实现的,但是union是使用两个结果集
(4)两个结果集的查询字段,顺序,数量要一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值