MySql的初学习 -- 第七章 -- 多表、外键、数据库设计
博客说明
文章内容输出来源:拉勾教育Java就业急训营
多表简述
实际使用数据库时,更多时候要多张表才能满足需求,单表有局限性
外键约束
什么是外键
外键指的是在 子表 中 与 主表 的主键对应的那个字段
使用外键约束可以让两张表之间产生一个对应关系,从而保证主从表的引用的完整性,从而形成多表
添加外键
-- 创建表时添加外键
-- 在SQL后加上即可
-- 格式:[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
-- 格式:FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
# 这两个格式区别在于一个有[CONSTRAINT] [外键约束名称],另外一个没有,这个平时可以省略,
# 如果省略后系统会自动生成一个外键名
-- 第一步,创建一个主表
#创建城市表
CREATE TABLE city(
cid INT PRIMARY KEY AUTO_INCREMENT,-- 城市ID
city_name VARCHAR(20)-- 城市名称
);
-- 第二步,创建一个子表与主表关联组成多表
#学生表
CREATE TABLE student(
tid INT PRIMARY KEY AUTO_INCREMENT,-- 学生ID
tname VARCHAR(20),-- 学生名称
tage INT,-- 学生年龄
tcity INT,--城市ID
#给外键取一个名字 #外键字段名 #主表名(主键字段名)
-- [CONSTRAINT] student_city_fk FOREIGN KEY(tcity) REFERENCES city(id)
FOREIGN KEY(tcity) REFERENCES city(id)
);
-- 创建表之后添加外键
-- 格式:ALTER TABLE 子表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
-- 这个和上面第二步效果一样
-- ALTER TABLE student ADD [CONSTRAINT] student_city_fk FOREIGN KEY(tcity) REFERENCES city(id);
ALTER TABLE student ADD FOREIGN KEY(tcity) REFERENCES city(id);
删除外键
-- 格式:ALTER TABLE 子表名 DROP FOREIGN KEY 外键名
ALTER TABLE student DROP FOREIGN KEY student_city_fk;
外键的注意事项
- 子表的外键类型必须与主表的主键类型一致
- 添加数据时,应先添加主表的数据
- 删除数据时,要先删除子表的数据
级联删除
作用:删除主表的数据时,同时删除与主表相关联的表的数据
人话:删主表数据时,如果子表数据有和主表数据有关联,一起删除
-- 需要在创建表时添加级联删除
-- 格式:ON DELETE CASCADE
#复制上面的学生表
CREATE TABLE student(
tid INT PRIMARY KEY AUTO_INCREMENT,-- 学生ID
tname VARCHAR(20),-- 学生名称
tage INT,-- 学生年龄
tcity INT,--城市ID
#给外键取一个名字 #外键字段名 #主表名(主键字段名)
-- [CONSTRAINT] student_city_fk FOREIGN KEY(tcity) REFERENCES city(id)
FOREIGN KEY(tcity) REFERENCES city(id)
ON DELETE CASCADE -- 添加级联删除
);
多表关系介绍(常见)
一对多关系(常见)
一对多 一一> 1:N
例子:班级一一>学生、部门一一>员工
多对多关系(常见)
多对多 一一> N:N
例子:学生一一>课程、演员一一>角色
一对一关系(不常见)
一对一 一一> 1:1
例子:人一一>身份证
一对一的外键需要设置唯一约束
多表查询
多表查询公式
- 查询几张表
- 表的连接条件
- 查询所需要的字段
- 查询的条件
例子:查询衣服表中卫衣分类下,价格大于500的商品名称和价格
1. 查询几张表 衣服表、价格表
2. 表的连接条件 从表.外键= 主表的主键
3. 查询所需要的字段 衣服表.name、价格表.价格
4. 查询的条件 衣服表.type = '卫衣' and 价格表.价格 > 500
SELECT
b.name,
a.价格
FROM 价格表(子表) a INNER JOIN 衣服表(主表) b
ON a.`外键id` = b.`id`;
交叉查询(基本不会使用)
-- 交叉查询,因为会产生笛卡尔积,所以 基本不会使用
-- 笛卡尔积:两个数的乘积
-- 格式:SELECT 字段名 FROM 表1, 表2;
SELECT * FROM table1,table2;
笛卡尔积:
内连接查询
特点:通过指定的条件去匹配两张表中的内容,匹配不上就不显示
别名
SELECT
a.`table_id`,
b.`table_name`,
FROM table1 a, table2 b where a.`table1_id` = b.`table2_id`;
隐式内连接
-- 格式:SELECT 字段名 FROM 表名 WHERE 连接条件(表1外键 = 表2主键)
SELECT * FROM table1 , table2 where table1_id = table2_id;
显式内连接
-- 格式:SELECT 字段名 FROM 子表 INNER JOIN 主表 on 连接条件(表1外键 = 表2主键)
-- INNER可以省略
SELECT * FROM table1 a INNER JOIN table2 b ON a.`table1_id` = b.`table2_id`;
外连接查询
左外连接
特点:以左表为基准匹配右表的数据,匹配得上就显示
如果匹配不上,左表中的数据正常显示,右表的数据显示为null
-- 格式:SELECT 字段名 FROM 左表(子表) LEFT JOIN 右表(主表) ON 连接条件(表1外键 = 表2主键)
SELECT * FROM table1 a LEFT JOIN table2 b ON a.`table1_id` = b.`table2_id`;
右外连接
特点:以右表为基准匹配左表的数据,匹配得上就显示
如果匹配不上,右表中的数据正常显示,左表的数据显示为null
-- 格式:SELECT 字段名 FROM 左表(子表) RIGHT JOIN 右表(主表) ON 连接条件(表1外键 = 表2主键)
SELECT * FROM table1 a RIGHT JOIN table2 b ON a.`table1_id` = b.`table2_id`;
各种连接方式的总结
子查询
特点:一条select语句的结构作为另外一条select语句的一部分
-- 要求:必须要放在小括号中
-- 格式:不知道怎么写格式,看例子吧
#查询班里最高分
SELECT MAX(score) FROM class;
#以最高分为条件查询名称(是谁拿了班第一)
#父SQL #子SQL
SELECT name FROM class WHERE score = (SELECT MAX(score) FROM class);
where型子查询
和上面演示一样
#查询班里最高分
SELECT MAX(score) FROM class;
#以最高分为条件查询名称(是谁拿了班第一)
#父SQL #子SQL
SELECT name FROM class WHERE score = (SELECT MAX(score) FROM class);
from型子查询
特点:将子查询的查询结构作为一张表使用
例子:查询分数,成绩大于600分,包括学生姓名、成绩、所属班级
分析:
表:成绩表、学生表、班级表
条件:成绩 > 600
查询字段:学生姓名、成绩、所属班级
连接条件:学生id = 班级id、成绩id = 学生id
SELECT
s.`name` '学生姓名',
a.`score` '成绩',
c.`name` '所属班级'
FROM
学生表 s INNER JOIN (SELECT * FROM 班级表) c ON s.`cid` = c.`id`,
成绩表 a INNER JOIN s ON a.`sid` = s.`id`
WHERE a.`score` > 600;
exists型子查询
特点:查询结果是单列多行的情况,可以将子查询的结果作为 父查询的 in函数 的条件使用
-- 格式:select 字段名 from 表名 where 字段 in(子查询)
例子:查询校服类和文具类下面的全部商品信息
1.获取校服类和文具类的id
SELECT id FROM 分类表 WHERE name IN('校服','文具');
2.根据获取到的分类id查找商品信息
SELECT
* FROM
商品表 WHERE 分类id IN
(SELECT id FROM 分类表 WHERE name IN('校服','文具'))
子查询总结
- 子查询如果查出的是一个字段(单列), 那就在where后面作为条件使用.
- 子查询如果查询出的是多个字段(多列), 就当做一张表使用(要起别名).
数据库设计
数据库三范式
三范式:空间最省原则
三范式指的是数据库设计的规则
作用就是为了创建 冗余较小、结构合理的数据库(以时间换空间)
范式就是设计数据库的要求(规范)
要求
- (1NF) 满足最低要求的范式
- (2NF) 满足第一范式的基础上,进一步满足更多的范式
- (3NF) 以此类推
特点
- (1NF) 列具有原子性,设计列要做到列不可拆分
- (2NF) 一张表只能描述一件事情
- (3NF) 消除传递依赖,表中的数据如果能被推导出来,就不要设计一个字段单独存储
反三范式
反三范式指的是增加冗余或者重复数据来提高数据库的读性能
浪费存储空间 节省查询时间(以空间换时间)
总结
- 尽量根据三范式的规则设计数据库
- 可以合理的加冗余字段来减少join操作(多表查询),可以让数据库执行得更快