MySQL进阶:约束、多表设计、多表查询与事务

一、前言

当你熟练掌握单表增删改查之后,会发现真实项目开发几乎不会只使用一张数据表。本篇文章依次讲解数据库约束、多表关系设计、多表查询(内连接、外连接、子查询)以及事务ACID四大特性。所有知识点循序渐进,配套实操SQL,学习完成后,你就能具备设计项目数据表、编写复杂查询SQL的能力。

二、数据库约束:概述与分类

1、约束的概念

• 约束是作用于表中列上的规则,用于限制加入表的数据

• 约束的存在保证了数据库中数据的正确性、有效性和完整性

2、约束的分类

|------|--------------------------------|-------------|
| 约束名称 | 描述 | 关键字 |
| 非空约束 | 保证列中所有数据不能有null值 | NOT NULL |
| 唯一约束 | 保证列中所有数据各不相同 | UNIQUE |
| 主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
| 检查约束 | 保证列中的值满足某一条件 | CHECK |
| 默认约束 | 保存数据时,未指定值则采取默认值 | DEFAULT |
| 外键约束 | 外键用来让两个表的数据之间建立链接,保证数据的一致性和完整性 | FOREUGN KEY |

注意:旧版本的MySQL不支持检查约束

3、约束案例(讲解前五种约束)

案例需求:

-- 员工表

create table emp(

id int, -- 员工id,主键且自增长

ename varchar(50), -- 员工姓名,非空且唯一

joindate date, -- 入职日期,非空

salary double(7,2), -- 工资,非空

bonus double(7,2) -- 奖金,如果没有奖金默认为0

);

• 主键约束非空且唯一

​​​​​​​

• 非空约束:值不能为空

• 唯一约束:不能重复,值唯一

• 默认约束:不添加值,采取默认值

注意:给null时不是默认值,值就是null

•❗上述我们的id功能还没实现自增长,自增长的实现要采用 auto_increment 关键字

4、非空约束
4.1 概念

非空约束用于保证列中所有数据不能有null值

4.2 语法
4.2.1 添加约束
sql 复制代码
-- 创建表时添加非空约束
create table 表名(
    列名 数据类型 not null,
    ...
);
sql 复制代码
-- 建表后添加非空约束
alter table 表名 modify 字段名 数据类型 not null;
4.2.2 删除约束
sql 复制代码
alter table 表名 modify 字段名 数据类型;

三、外键约束详解

1、概念

• 外键用来关联两张表,分为父表(主表)和子表(从表),保证关联数据的一致性和完整性。举个例子:部门表(父表)和员工表(子表),员工表保存部门id,通过外键约束,不能给员工分配在一个不存在的部门。

2、语法
2.1 添加约束
sql 复制代码
-- 创建表时添加外键约束
create table 表名(
    列名 数据类型,
    ...
    [constraint] [外键名称] foreign key(外键列名) references 主表(主表列名)
);
sql 复制代码
-- 建完表后添加外键约束
alter table 表名 add constraint 外键名称 foreign key(外键字段名称) references 主表名称(主表列名称);
2.2 删除约束
sql 复制代码
alter table 表名 drop foreign key 外键名称;
3、外键约束案例

创建两个表:部门表(主表)、员工表(从表)

此时已经建立物理连接,删除研发部则报错,因为员工表中有研发部的员工,研发部不为空

删除外键:

❗开发提示:很多企业项目不推荐使用物理外键,依靠业务代码维护关联关系,避免外键带来性能问题。

四、数据库多表设计与表关系

1、数据库设计---简介
1.1 软件研发步骤
1.2 数据库设计概念

• 数据库设计就是根据业务系统的具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型

• 建立数据库中的表结构以及表与表之间的关联关系的过程

• 有哪些表?表里有哪些字段?表和表之间有什么关系?

1.3 数据库设计的步骤

① 需求分析(数据是什么?数据具有哪些属性?数据与属性的特点是什么?)

② 逻辑分析(通过ER图对数据库进行逻辑建模,不需要考虑我们所选用的数据库管理系统)

③ 物理设计(根据数据库自身的特点把逻辑设计转换为物理设计)

④ 维护设计(1.对新的需求进行建表;2.表优化)

2、三种常见表关系
2.1 一对多(最常用)

• 例如:部门和员工

• 一个部门对应多个员工,一个员工对应一个部门

2.2 多对多

• 例如:商品和订单、学生和课程

• 一个商品对应多个订单,一个订单包含多个商品

• 一个学生上多门课程,一门课程包含多个学生

2.3 一对一

• 例如:用户和用户详情

• 一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

3、多表关系实现
3.1 表关系之一对多

• 一对多(多对一):

• 如:部门表和员工表

• 一个部门对应多个员工,一个员工对应一个部门

• 实现方式:在多的一方建立外键,指向一的一方的主键(讲解外键约束时演示过)

3.2 表关系之多对多

• 多对多:

• 如:订单和商品

• 一个商品对应多个订单,一个订单包含多个商品

• 实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

代码演示:

3.3 表关系之一对一

• 一对一:

• 如:用户和用户详情

• 一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

• 实现方式:在任意一方加入外键,关联另一方主键,并且设置外键为唯一(unique)(类比一对多)

五、多表联合查询

1、什么是笛卡尔积

有 A、B 两个集合,取 A、B 所有的组合情况

多张表直接查询,所有数据无序全部组合,产生大量无效数据。

sql 复制代码
-- 产生笛卡尔积(错误写法)
select * from 表名,表名;

如上,有很多数据都是无效数据,所以我们的核心是添加条件过滤掉无效笛卡尔积数据!!!

多表查询可通过连接查询和子查询来实现,而连接查询又分为内连接和外连接。

2、内连接 inner join ... on

作用:查询两张表能够匹配上的数据(相当于查询A、B交集部分),匹配不到的数据不会显示

sql 复制代码
-- 隐式内连接
-- select 字段列表 from 表1,表2,... where 条件;
select * from staff,department where staff.dep_id=department.id;

-- 显式内连接(推荐写法)
-- select 字段列表 from 表1 [inner] join 表2 on 条件;
select * from staff inner join department on staff.dep_id=department.id;
3、外连接
3.1 左外连接 left join ... on

查询左表全部数据(相当于查询A表所有数据和交集部分数据),匹配不到右表数据,右表字段填充null。

sql 复制代码
-- select 字段列表 from 表1 left [outer] join 表2 on 条件;
select * from staff left outer join department on staff.dep_id=department.id;

查询staff表所有数据和对应的部门信息:

3.2 右外连接 right join ... on

查询右表全部数据(相当于查询B表所有数据和交集部分数据),匹配不到左表数据,左表字段填充null。

sql 复制代码
-- select 字段列表 from 表1 right [outer] join 表2 on 条件;
select * from staff right outer join department on staff.dep_id=department.id;

查询department表所有数据和对应的员工信息:

六、子查询

子查询:一条SQL语句中嵌套另一条select查询语句,嵌套查询结果可以作为条件、临时表使用。

子查询根据查询结果不同,作用不同分为三类子查询。

1、标量子查询(单行单列)

返回单个值(一行一列),可以直接用 = != > < 等条件判断

sql 复制代码
select 字段列表 from 表 where 字段名 = (子查询);

查询研发部所有员工信息:

2、列子查询(多行单列)

返回一列多行,搭配 in any all 等关键字进行条件判断

sql 复制代码
select 字段列表 from 表 where 字段名 in (子查询);

查询研发部和销售部所有员工信息:

3、表子查询(多行多列)

返回多行多列,当作虚拟表使用,外层继续关联查询

sql 复制代码
select 字段列表 from (子查询) where 条件;

查询年龄是18以后(不包括18岁)的员工信息和部门信息:

❗注意:当使用虚拟表时,必须给原始表起别名,否则会报错!!!

七、数据库事务与四大特征ACID

1、事务简介

• 数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令

• 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败

• 事务是一个不可分割的工作逻辑单元

• 经典场景:转账、A扣款和B收款必须同时成功

2、事务基础操作
sql 复制代码
-- 开启事务
start transaction;
或者    begin;
-- 提交事务
commit;
-- 回滚事务
rollback;

转账示例演示:

如果不开启事务,就会发现出错前面成功操作,后面则操作失败

开启事务后则不会出现问题

3、事务的四大特征 ACID

• 原子性(Atomicity):事务不可分割,要么同时成功,要么同时失败

• 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态

• 隔离性(Isolation):多个事务并发执行,互相之间互不干扰

• 持久性(Durability):事务一旦提交或回滚,修改永久保存到数据库,断电不丢失

4、MySQL默认提交

在MySQL里面,每条SQL语句都是默认提交的。

sql 复制代码
-- 查询事务的默认提交方式
select @@autocommit;
-- 修改事务的提交方式 → 手动提交
set @@autocommit=0;

八、结语

本篇我们完成了MySQL进阶核心内容学习:约束保障数据规范、多表关系教会我们如何设计项目数据表:内连接、外连接、子查询是开发中高频使用的复杂查询语法;事务保证连续数据操作的安全性。掌握本章全部内容后,我们就可以进入JDBC的学习,打通Java后端程序和MySQL数据库的交互,实现Java代码操作数据库。

相关推荐
技术长镜头1 小时前
别再只会“加索引”:从磁盘页到 B+Tree,彻底理解 MySQL 索引的设计与运行
后端·mysql
上玄code1 小时前
【Agent精讲】调一个LLMAPI背后的工程问题
java·开发语言·python·chatgpt
李冰然1 小时前
深入Java集合框架:ArrayList源码解析(JDK 8)
java
小小啊python1 小时前
IDEA中SpringBoot项目配置热部署
java·ide·intellij-idea·springboot·热部署
weixin_431600441 小时前
NestJS 入门(9):连上数据库,SQL 写在哪?
数据库·后端·sql·学习·nest.js
Java成神之路-1 小时前
Spring AI Alibaba 实现多轮对话记忆:ChatMemory 与 Redis 持久化实战
java·springaialibaba
JAVA面经实录9172 小时前
网络编程基础(Java Web/分布式前置·完整版)(十一)
java·前端·网络
代码方舟2 小时前
零信任架构实战:基于天远人企关联构建自动化企业尽职调查网关
java·人工智能·架构·自动化
math_hongfan2 小时前
一对多的数据库姻缘:ArkTS 为鸿蒙订单设计外键与明细表
数据库·华为·harmonyos