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;

外键的注意事项

  1. 子表的外键类型必须与主表的主键类型一致
  2. 添加数据时,应先添加主表的数据
  3. 删除数据时,要先删除子表的数据

级联删除

作用:删除主表的数据时,同时删除与主表相关联的表的数据
人话:删主表数据时,如果子表数据有和主表数据有关联,一起删除

-- 需要在创建表时添加级联删除
-- 格式: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
例子:人一一>身份证
一对一的外键需要设置唯一约束

多表查询

多表查询公式

  1. 查询几张表
  2. 表的连接条件
  3. 查询所需要的字段
  4. 查询的条件
例子:查询衣服表中卫衣分类下,价格大于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('校服','文具'))

子查询总结

  1. 子查询如果查出的是一个字段(单列), 那就在where后面作为条件使用.
  2. 子查询如果查询出的是多个字段(多列), 就当做一张表使用(要起别名).

数据库设计

数据库三范式

三范式:空间最省原则

三范式指的是数据库设计的规则
作用就是为了创建 冗余较小、结构合理的数据库(以时间换空间)
范式就是设计数据库的要求(规范)

要求

  1. (1NF) 满足最低要求的范式
  2. (2NF) 满足第一范式的基础上,进一步满足更多的范式
  3. (3NF) 以此类推

特点

  1. (1NF) 列具有原子性,设计列要做到列不可拆分
  2. (2NF) 一张表只能描述一件事情
  3. (3NF) 消除传递依赖,表中的数据如果能被推导出来,就不要设计一个字段单独存储

反三范式

反三范式指的是增加冗余或者重复数据提高数据库的读性能
浪费存储空间 节省查询时间(以空间换时间)

总结

  1. 尽量根据三范式的规则设计数据库
  2. 可以合理的加冗余字段来减少join操作(多表查询),可以让数据库执行得更快

猜你喜欢

转载自blog.csdn.net/zy3062231314/article/details/112976321