【MySQL】数据库约束和多表查询

目录

1.前言

2.数据库约束

2.1约束类型

2.2 NULL约束

2.3 NUIQUE:唯一约束

2.4 DEFAULT:默认值约束

2.5 PRIMARY KEY:主键约束

2.6 FOREIGN KEY:外键约束

1.7 CHECK约束

3.表的设计 

3.1一对一

3.2一对多

3.3多对多

4.新增

5.查询

5.1聚合查询

5.1.1聚合函数

5.1.2 GROUP BY子句

5.1.3 HAVING

5.2联合查询

5.2.1内连接

5.2.2外连接

5.2.3自连接

5.2.4子查询

5.2.5合并查询

6.总结 


1.前言

我们上一次介绍了MySQL数据库关于表的增删改查,在平时是用的过程还需要对数据库进行约束以及多表查询,因此今天跟大家分享并介绍数据库约束和多表查询的内容。

2.数据库约束

2.1约束类型

NOT NULL: 指示某列不能存储NULL值。

UNIQUE:保证某列的每行必须有唯一的值。

DEFAULT:规定没有给列赋值时的默认值。

PRIMARY KEY:确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。

FOREIGN KEY:保证一个表中的数据匹配另一个表中的值的参照完整性。

CHECK:保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略CHECK子句

2.2 NULL约束

我们在数据库创建表时,可以指定某列不为空,比如我们在创建一个学生表时,可以对表的结构进行设置。

-- 创建学生表并设置学生表结构
create table student (
id int not null,
sn int,
name varchar(20),
qq_mail varchar(20)
);

2.3 NUIQUE:唯一约束

指定sn列中的值唯一且不重复的,比如我们重新设置学生表的结构:

-- 重新设置学生表结构
drop table if exists student;
create table student (
id int not null,
sn int unique,
name varchar(20),
qq_mail varchar(20)
);

2.4 DEFAULT:默认值约束

指定插入数据时, name 列为空,默认值 unkown
-- 重新设置学生表结构
drop table if exists student;
create table student (
id int not null,
sn int unique,
name varchar(20)  default 'unkown',
qq_mail varchar(20)
);

2.5 PRIMARY KEY:主键约束

指定 id 列为主键:
-- 重新设置学生表结构
drop table if exists student;
create table student (
id int not null primary key,
sn int unique,
name varchar(20)  default 'unkown',
qq_mail varchar(20)
);

对于整数类型的主键,常配搭自增长 auto_increment 来使用。插入数据对应字段不给值时,使用最大值+1
-- 主键是 NOT NULL 和 UNIQUE 的结合,可以不用 NOT NULL
id INT PRIMARY KEY auto_increment

2.6 FOREIGN KEY:外键约束

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

foreign key (字段名) references 主表(列)

下面以创建一个班级表和学生表为例:

  • 创建班级表classes,id为主键
-- 创建班级表,有使用MySQL关键字作为字段时,需要使用``来标识
create table classes (
id INT PRIMARY KEY auto_increment,
name VARCHAR(20),
`desc` VARCHAR(100)
);

  •  创建学生表student,一个学生对于一个班级,一个班级对应多个学生。使用id为主键,class_id为外键,关联班级表id。
-- 创建学生表
drop table if exists student;
create table student (
id int not null primary key,
sn int unique,
name varchar(20)  default 'unkown',
qq_mail varchar(20),
classes_id int,
foreign key (classes_id) references classes(id)
);

1.7 CHECK约束

MySQL使用时不报错,但忽略该约束。

create table test_user (
id int,
name varchar(20),
sex varchar(1),
check (sex = '男' or sex = '女')
);

3.表的设计 

3.1一对一

比如:一个学生只能对应一个身份证,一个身份证也只能对应一个学生。

3.2一对多

一个班级有多个学生,但一个学生只能对应一个班级。

3.3多对多

一个学生能够选择多门课程,一个课程可以被多个学生选择。

4.新增

语法:

INSERT INTO table_name [(column [, column ...])] SELECT ...
给大家举个例子:创建一张用户表,设计有 name 姓名、 email 邮箱、 sex 性别、 mobile 手机号字段。需要把已有的学生数据复制进来,可以复制的字段为name,qq_ mail。
-- 创建用户表
DROP TABLE IF EXISTS test_user;
CREATE TABLE test_user (
id INT primary key auto_increment,
name VARCHAR(20) comment '姓名',
age INT comment '年龄',
email VARCHAR(20) comment '邮箱',
sex varchar(1) comment '性别',
mobile varchar(20) comment '手机号'
);-- 新增班级数据
insert into classes values(601,"六年级一班","1班");-- 新增学生数据
insert into student values(1,100,"张三","123@qq.com",601);
insert into student values(2,101,"李四","456@qq.com",601);-- 将学生表中的所有数据复制到用户表
insert into test_user(name, email) select name, qq_mail from student;-- 查询用户表
select * from test_user;

5.查询

5.1聚合查询

5.1.1聚合函数

常见的统计总数、计算平局值等操作,可以使用 聚合函数 来实现,常见的聚合函数有:
函数说明
COUNT([DISTINCT] expr)返回查询到的数据的数量

SUM([DISTINCT] expr)

返回查询到的数据的总和,不是数字没有意义
AVG([DISTINCT] expr)返回查询到的数据的平均值,不是数字没有意义
MAX([DISTINCT] expr)返回查询到的数据的最大值,不是数字没有意义
MIN([DISTINCT] expr)返回查询到的数据的最小值,不是数字没有意义
  • COUNT
-- 统计班级共有多少同学
SELECT COUNT(*) FROM student;-- 统计班级收集的qq_mail 有多少个,qq_mail 为 NULL 的数据不会计入结果
SELECT COUNT(qq_mail) FROM student;

  • SUM
-- 统计数学成绩总分
select sum(math) from exam;-- 统计所有数学成绩不及格(<60)人的数学总分,没有则返回NULL
select sum(math) from exam where math < 60;

  • AVG
-- 统计平均总分
select avg(Chinese + math + English) from exam;

  • MAX
-- 返回数学最高分
select max(math) from exam;

  • MIN
-- 返回 > 70 分以上的数学最低分
select min(math) from exam where math > 70;

5.1.2 GROUP BY子句

SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足: 使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。
语法:
select column1, sum(column2), .. fromtablegroupby column1,column3;

举个例子:

  • 准备测试表及数据:员工表,有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)
);-- 添加员工数据
insert into emp(name, role, salary) values
('张三','服务员', 1000.20),
('李四','游戏陪玩', 2000.99),
('孙悟空','游戏角色', 999.11),
('猪无能','游戏角色', 333.5),
('沙和尚','游戏角色', 700.33),
('王五','董事长', 12000.66);

  • 查询每个角色的最高工资、最低工资和平均工资。
select role, max(salary), min(salary), avg(salary) from emp group by role;

5.1.3 HAVING

GROUP BY 子句进行分组以后 ,需要对分组结果再 进行条件过滤 时, 不能使用 WHERE 语句 ,而 需要用HAVING。
  • 显示平均工资低于1500的角色和它的平均工资
select role, avg(salary) from emp group by role having avg(salary) < 1500;

5.2联合查询

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

注意:关联查询可以对关联表使用别名。、

下面展示初始化测试数据:

-- 在班级表中新增数据
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');-- 在学生表中新增数据
insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);-- 创建课程表
create table course(id int primary key auto_increment, name varchar(20));-- 在课程表中新增数据
insert into course(name) values
('Java'),
('中国传统文化'),
('计算机原理'),
('语文'),
('高阶数学'),
('英文');-- 创建成绩表
create table score(score decimal(3, 1), student_id int, course_id int);--在成绩表中新增数据
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);

 

 

5.2.1内连接

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

例如:1)查询许仙同学的成绩

select stu.name, sco.score from student as stu join score as sco on stu.id = sco.student_id and stu.name = '许仙';-- 也可以采用下面这种方法
select stu.name, sco.score from student as stu, score as sco where stu.id = sco.student_id and stu.name = '许仙';

2)查询所有同学的总成绩,及同学的个人信息:

-- 成绩表对学生表是多对一关系,查询总成绩是根据成绩表的同学id来进行分组的
select stu.sn, stu.name, stu.qq_mail, sum(sco.score) 
from 
student as stu join score as sco 
on stu.id = sco.student_id 
group by sco.student_id;

3)查询所有同学的成绩,及同学的个人信息: 

-- 查询出来的都是有成绩的同学,“老外学中文”同学没有显示
select * from student stu join score sco on stu.id=sco.student_id;

-- 学生表、成绩表、课程表3张表关联查询
select stu.id,stu.sn,stu.NAME,stu.qq_mail,sco.score,sco.course_id,cou.NAME
FROM
student stu
JOIN score sco ON stu.id = sco.student_id
JOIN course cou ON sco.course_id = cou.id 
order by stu.id;

5.2.2外连接

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

语法:

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

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

-- “老外学中文”同学没有考试成绩,也显示出来了
select * from student stu left join score sco on stu.id=sco.student_id;
-- 对应的右外连接为:
select * from  score sco right join student stu on stu.id=sco.student_id;

-- 学生表、成绩表、课程表3张表关联查询
SELECT stu.id,stu.sn,stu.NAME,stu.qq_mail,sco.score,sco.course_id,cou.NAME
FROM
student stu
LEFT JOIN score sco ON stu.id = sco.student_id     
LEFT JOIN course cou ON sco.course_id = cou.id 
order by stu.id;

5.2.3自连接

自连接是指在同一张表连接自身进行查询。
例如:显示所有"计算机原理"成绩比"Java"成绩高的成绩信息。
-- 先查询"计算机原理"和"Java"课程的id
select id, name from course where name = 'Java' or name = '计算机原理';-- 再查询成绩表中,"计算机原理"成绩比"Java"成绩好的信息
select s1.* 
from score s1,score s2 
where
s1.student_id = s2.student_id
and s1.score < s2.score and s1.course_id = 1
and s2.course_id = 3;

5.2.4子查询

子查询是指嵌入在其他 sql 语句中的 select 语句,也叫嵌套查询。
注意:编程中的基本思想原则化繁为简,但子查询是化简为繁,我们要慎重使用,避免出错。
  • 单行子查询:返回一行记录的子查询
比如:查询与 不想毕业 同学的同班同学:
select * from student where classes_id=(select classes_id from student where name='不想毕业');

  • 多行子查询:返回多行记录的子查询
例如:查询 语文 英文 课程的成绩信息。
1. [NOT] IN关键字:
-- 使用IN
select * from score where course_id in (select id from course where name='语文'or name='英文');-- 使用 NOT IN
select * from score where course_id not in (select id from course where name!='语文'and name!='英文');

注意:

from 子句中使用子查询:子查询语句出现在 from 子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

5.2.5合并查询

在实际应用中,为了合并多个 select 的执行结果,可以使用集合操作符 union,union all 。使用 UNION和UNION ALL 时,前后查询的结果集中,字段需要一致。
  • union

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

例如:查询id小于3,或者名字为英文的课程:

select * from course where id<3
union
select * from course where name='英文';-- 或者使用or来实现
select * from course where id<3 or name='英文';

  • union all
该操作符用于取得两个结果集的并集。 当使用该操作符时,不会去掉结果集中的重复行。
举个例子:查询 id 小于 3 ,或者名字为 “Java” 的课程
-- 可以看到结果集中出现重复数据Java
select * from course where id<3
union all
select * from course where name='Java';

6.总结 

SQL 查询中各个关键字的执行先后顺序: from > on> join > where > group by > with > having > select > distinct > order by > limit, 我们在编写SQL语句时要按照上面的执行顺序去编写,才能成功运行获取到想要查询的数据,以上就是本次所介绍的内容,我们下次再跟继续大家分享MySQL数据库中的索引与事务!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/397914.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3-02-vue3中的组件通信

目录 组件通信一、vue3组件通信和vue2的区别二、父子通信2.1 props通信1&#xff09;父→子传递数据&#xff08;父组件向子组件传递数据&#xff09;2&#xff09;子→父传递数据 2.2 v-model1&#xff09;v-model的本质2&#xff09;给modelValue起别名3&#xff09;$event 2…

用Python制作开心消消乐游戏|附源码

制作一个完整的“开心消消乐”风格的游戏在Python中是一个相对复杂的项目&#xff0c;因为它涉及到图形界面、游戏逻辑、动画效果以及用户交互等多个方面。不过&#xff0c;我可以为你提供一个简化的版本和概念框架&#xff0c;帮助你理解如何开始这个项目&#xff0c;并提供一…

英伟达元宇宙平台Omniverse的学习,技术调研

NVIDIA Omniverse™ 是一个基于 USD (Universal Scene Description) 的可扩展平台&#xff0c;可使个人和团队更快地构建自定义 3D 工作流并模拟大型虚拟世界。 Omniverse&#xff1a;三维设计协同、模拟的开发平台&#xff0c;实现3D实时渲染&#xff0c;RTX光线追踪技术 协…

职场英语培训柯桥外语学校学外语学英语到银泰泓畅学校

“工作量太大了”怎么说&#xff1f; 导致加班有一个非常大的因素就是&#xff1a; “工作量太大了&#xff01;” “ 注意&#xff1a;形容工作量太大不使用“big”一词&#xff0c;要用heavy&#xff0c;相应的要说工作量较小&#xff0c;可以用light. 工作量大/小 &…

数据中心互连的关键要素和核心技术

数据中心互连&#xff08;DCI&#xff09;依靠其关键要素和核心技术进行的高效、可靠和高速的连接&#xff0c;实现了数据中心跨区域连接的即时通信和数据交换&#xff0c;成为了现代数字通信基础设施的重要组成部分。从光模块和多路复用设备到网络协议和管理系统&#xff0c;D…

Leetcode75-5 反转字符串的元音字母

本质上来说就是反转字符串 一部分需要反转 一部分不动 思路: 1.用String字符串倒序拼接 就是过滤掉不是元音字符 然后把所有的字符&#xff08;非元音的直接复制过来 元音字母直接从反转的字符串里边复制即可&#xff09; 2.看了题解发现自己写的啰嗦了 就是一个双指针问题用…

酒店行业如何利用XML进行营销短信

随着信息社会的到来&#xff0c;消费者获得会所的服务也从单纯的电话方式&#xff0c;逐渐转变为电话、互联网、传真&#xff0c;群发短信等多种媒体并行的方式。今天着重介绍下酒店行业如何利用短信平台进行营销。 群发短信业务对酒店起到的效率&#xff1a;根据新产品或服务向…

java实现解析pdf格式发票

为了减少用户工作量及误操作的可能性&#xff0c;需要实现用户上传PDF格式的发票&#xff0c;系统通过解析PDF文件获取发票内容&#xff0c;并直接将其写入表单。以下文章记录了功能实现的代码。 发票样式 发票内容解析 引用Maven 使用pdfbox <dependency><groupI…

Spring Boot - 在Spring Boot中实现灵活的API版本控制(下)_ 封装场景启动器Starter

文章目录 Pre设计思路ApiVersion 功能特性使用示例配置示例 ProjectStarter Code自定义注解 ApiVersion配置属性类用于管理API版本自动配置基于Spring MVC的API版本控制实现WebMvcRegistrations接口&#xff0c;用于自定义WebMvc的注册逻辑扩展RequestMappingHandlerMapping的类…

前端CSS画图形

我以前一直很好奇&#xff0c;这些下拉菜单中的小箭头是怎么实现的&#xff0c;直到我看到了进阶的CSS。 OK&#xff0c;let me tell you hao to do. 想要实现这个效果&#xff0c;方法很多&#xff0c;我知道的就两个&#xff1a; 图片作弊法&#xff0c;CSS妙用法 图片作弊…

uni-app 开发App时调用uni-push 实现在线系统消息推送通知 保姆教程

一、引言 在开发App时避免不了需要推送系统通知&#xff0c;以提高用户的使用体验。在自己的一个工具型的小app上全流程接入了uni-push2.0的推送能力&#xff0c;做个记录&#xff0c;以防后期需要用到。在阅读本教程前最好先看看官方文档&#xff0c;结合官方文档使用&#xf…

下载免费设计素材,有这7个网站就够了

7个免费设计素材网站&#xff0c;这些网站提供了大量的免费资源&#xff0c;包括图片、字体、图标、模板等&#xff0c;涵盖了多种风格和主题&#xff0c;能够满足不同设计师和创作者的需求。无论是用于个人项目还是商业用途&#xff0c;这些网站都能给你提供丰富的选择&#x…

10步搞定Python爬虫从零到精通!

学习Python网络爬虫可以分为以下几个步骤&#xff0c;每一步都包括必要的细节和示例代码&#xff0c;以帮助你从零开始掌握这一技能。 第一步&#xff1a;理解网络爬虫基础 什么是网络爬虫&#xff1f; 网络爬虫是一种自动化程序,用来从互联网上收集数据.它通过发送 HTTP 请求…

【数据结构】五、树:7.哈夫曼树、哈夫曼编码

3.哈夫曼树和哈夫曼编码 文章目录 3.哈夫曼树和哈夫曼编码3.1带权路径长度3.2哈夫曼树的定义和原理3.3哈夫曼树的构造代码实现 3.4特点3.5哈夫曼编码压缩比代码实现 3.6哈夫曼树-C 3.1带权路径长度 #mermaid-svg-yeVKyVnDwvdIc5ML {font-family:"trebuchet ms",verda…

CSS 实现两边固定宽,中间自适应

0. **Flexbox 实现**&#xff1a; css复制代码.container { display: flex; } ​ .fixed { width: 200px; /* 两边固定宽度 */ } ​ .flexible { flex: 1; /* 中间自适应 */ } html复制代码<div class…

数据科学 - Sklearn库总结

1. 前言 通过上几章对数据预处理的理解&#xff0c;最后来到我们数据分析的核心之一&#xff0c;机器学习。 机器学习涵盖了许多方面&#xff0c;如若每一次处理都是通过手写代码的方式去处理我们的数据集是十分繁琐&#xff0c;复杂的。但在scikit-learn库中&#xff0c;提供…

带你彻底搞懂useLayoutEffect的使用场景

开篇第一句: useLayoutEffect 可能会影响性能。尽可能使用 useEffect。 useLayoutEffect 是 useEffect 的一个版本&#xff0c;在浏览器重新绘制屏幕之前触发。 使用方法 useLayoutEffect(setup, dependencies?)调用 useLayoutEffect 在浏览器重新绘制屏幕之前进行布局测量&…

lvs详解及实例配置

目录 1.什么是负载均衡 1.1为什么用负载均衡 1.2.负载均衡类型 1.2.1.四层负载均衡 1.2.2.七层负载均衡 1.3 四层和七层的区别 2.LVS介绍 2.1LVS 的优势与不足 2.2LVS 核心组件和专业术语 3.ipvsadm命令 4.LVS集群中的增删改 4.1.管理集群服务中的增删改 4.2.管理集…

用户态tcp协议栈四次挥手-服务端发送fin时,客户端不返回ac

问题&#xff1a; 四次挥手时&#xff0c;服务端发送fin后&#xff0c;客户端不发送ack&#xff0c;反而过了2min后发了个rst报文 62505是客户端&#xff0c;8889是服务端 解决&#xff1a; 服务端返回fin报文时带上ack标记

数据结构(邓俊辉)学习笔记】优先级队列 03——完全二叉堆:结构

文章目录 1.完全二叉树2.结构性3.形神具备4.堆序性 1.完全二叉树 在上一节我们看到&#xff0c;就优先级队列的实现方式而言&#xff0c;采用基本的向量结构并不足够&#xff0c;而采用更高级的树形结构&#xff0c;虽然完全可以高效率地实现优先级队列&#xff0c;但却有杀鸡…