MySQL基础----[多表设计,数据库设计范式,内连接,外连接,数据库备份及导入还原 ]

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL基础----[多表设计,数据库设计范式,内连接,外连接,数据库备份及导入还原 ]相关的知识,希望对你有一定的参考价值。


对于数据表的列属性设置时,有时会出现数据冗余的现象;那么就需要将表结构合理设计;将原来创建了多个列的一张表进行合理分类;形成多个表;

数据冗余是指数据之间的重复,也可以说是同一数据存储在不同数据文件中的现象。 可以说增加数据的独立性和减少数据冗余是企业范围信息资源管理和大规模信息系统获得成功的前提条件。


数据库设计范式


那么在设计数据库时就要考虑到数据冗余的问题;这就需要特定的规定来约束数据库的设计;在关系型数据库中就称为数据库设计范式

关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第四范式(4NF)和第五范式(5NF)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。

第一范式(1NF):保持数据库的列的原子性.(即设计的列不可再分为别的列).

数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性
在任何一个关系数据库中,第一范式(1NF)是对关系模式的设计基本要求,一般设计中都必须满足第一范式(1NF)。不过有些关系模型中突破了1NF的限制,这种称为非1NF的关系模型。换句话说,是否必须满足1NF的最低要求,主要依赖于所使用的关系模型

第二范式(2NF):必须要有主键;由于主键的数据是唯一的;可以通过主键的一个数据精确地定位到它所在的行的信息;其他列的数据都依赖于主键所在的列.

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式。
如果存在不符合第二范式的情况,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。

第三范式(3NF):一张表就存储一类信息;会关联其他表,且消除了数据冗余.

属性不能传递依赖于主属性(属性不依赖于其它非主键属性)
第三范式(3NF)是在第二范式(2NF)的基础上建立起来的,即满足第三范式(3NF)必须先满足第二范式(2NF)。
如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。



外键(foreign key)


在设计表时,表与表之间关联时,没有任何约束;即为弱关系.表与表之间存在约束,即有强关系.

外键约束就是连接表与表之间的桥梁;

外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系;外键可以是空值,也可以重复;外键是用来建立与其他表联系用的;外键可以有多个.
设置外键的表是从表;它所关联的表就是主表.

可以在创建表时添加外键约束;

#外键名可以省略;可以设置多个列为外键;
[CONSTRAINT <外键名>] FOREIGN KEY 字段名 [,字段名2,…] REFERENCES <主表名> 主键列1 [,主键列2,…];

也可以在创建表之后修改表时添加外键约束;

ALTER TABLE 表名 ADD [CONSTRAINT 约束名]   FOREIGN KEY(外键列) REFERENCES 关联主表(主键);

删除外键约束;

ALTER TABLE  表名  DROP FOREIGN KEY  外键约束名;

在设置了主键之后;需要注意的是:

  • 在删除主表的数据之前;首先要删除从表的对应数据;负责会报出约束错误警告.
  • 如果要删除整张表;首先要删除从表(即设置外键的表)
  • 不要随意更改主表的值
  • 如果主表没有存储记录数据;那么从表也无法添加该数据.

对于接下来的学习,首先新建数据库,数据表;并且插入部分数据;

新建数据库 studentworld_db
CREATE DATABASE studentworld_db;

新建班级表;

#新建班级表;
CREATE TABLE t_grade(
            #班级ID,设置为主键且自动增长,
            id INT  PRIMARY KEY AUTO_INCREMENT COMMENT '班级号',
            #班级名,最大长度为5,不能为空,
            class VARCHAR(5)NOT NULL COMMENT '班级');

新建学生表

#新建学生表;
CREATE TABLE t_student(
            #学号,设置为主键且自动增长;
            stu_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
            #姓名,最大长度为5,不能为空;
            NAME VARCHAR(5)NOT NULL COMMENT '姓名',
            #性别;
            sex char(1) COMMENT'性别',
            #生日,日期类型;
            birthday DATE COMMENT '生日',
            #手机号,11位;
            phone char(11) COMMENT '手机号',
            #班级ID,设置为外键;
            gra_id INT COMMENT '班级号',
            CONSTRAINT graid_fk FOREIGN KEY   (gra_id) REFERENCES t_grade(id),
            #注册时间;
            res_time DATETIME COMMENT '注册时间');

新建课程表;

#课程表;
CREATE TABLE t_course(
            #课程号,设置为主键;
            cou_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '课程号',
            #课程名;
            Cname  VARCHAR(5) COMMENT '课程名');

新建选课表;

#选课表;
CREATE TABLE t_student_course(
            #学号,课程号,且设置外键;
            stu_id INT COMMENT '学号',
            cou_id INT COMMENT '课程号',
            CONSTRAINT stuid_fk FOREIGN KEY (stu_id) REFERENCES t_student(stu_id),
            CONSTRAINT couid_fk FOREIGN KEY (cou_id) REFERENCES t_course(cou_id));      

插入数据

#插入数据;
#班级表;
INSERT INTO t_grade(id,class)
            VALUES(1801,'一班'),
                  (1802,'二班'),
                  (1803,'三班'),
                  (1804,'四班'),
                  (1805,'五班');
#学生表;
INSERT INTO t_student(stu_id,NAME,sex,birthday,phone,gra_id,res_time)
            VALUES(001,'鱼干王','男','2018-6-6','13666666666',1802,now()), 
                  (002,'小树人','女','2019-8-12','15666666666',1801,now()),
                  (003,'黑西装','男','2018-12-10','12345698745',1801,now()),
                  (004,'天山狐妖','男','2008-1-9','11111745871',1802,now()),
                  (005,'peter','男','2005-6-3','18298711111',1803,now()),
                  (006,'MARTU','男','2018-3-6','19998711111',1803,now()),
                  (007,'tutu','男','2015-9-3','12398711111',1803,now()),
                  (008,'黑骑士','男','2003-6-1','16985222222',1803,now()),
                  (009,'蓝骑士','男','2001-1-8','19999999999',1804,now()),
                  (010,'小红帽','女','2009-3-1','12222222222',1804,now()),
                  (011,'狼人','男','2020-3-5','11111111111',1805,now()),
                  (012,'暗星','女','2016-6-12','15622233333',1804,now()),
                  (013,'糖果','女','2015-6-15','13333333333',1805,now()),
                  (014,'船长','男','2006-6-8','15698745222',1804,now()),
                  (015,'雪怪','男','2001-8-12','12332112331',1801,now()),
                  (016,'山猫','女','2005-1-1','11111232323',1801,now()),
                  (017,'苍穹','男','2016-5-6','12654123654',1802,now()),
                  (018,'欧米伽','男','2018-2-2','16666666666',1803,now()),
                  (019,'双面特工','女','2016-5-5','15987852014',1804,now());
#课程表;
INSERT INTO t_course(cou_id,Cname)
            VALUES(101,'数据结构'),
                  (102,'JAVA'),
                  (103,'C#'),
                  (104,'算法'),
                  (105,'操作系统');
#选课表;
INSERT INTO t_student_course(stu_id,cou_id)
            VALUES(001,101),
                  (001,102),
                  (001,103),
                  (001,104),
                  (001,105),
                  (002,102),
                  (002,103),
                  (003,101),
                  (003,102),
                  (003,103),
                  (003,105),
                  (004,102),
                  (004,103),
                  (006,102),
                  (006,102),
                  (007,105),
                  (007,104),
                  (008,102),
                  (008,104),
                  (008,104),
                  (009,102),
                  (009,101),
                  (009,103);

关联查询(多表查询)


查询的字段来自于多个表


在没有建立有效的连接时;

笛卡尔乘积现象:表1有m行,表2有n行,结果=m*n
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件

就例如:

#查询学生表和课程表;
SELECT * FROM t_student,t_grade;

结果:没有关联的数据合并在了一起;这样拼接出来的结果很难去比对数据.

在这里插入图片描述


那么在多表查询时,会按照不同的功能进行分类;内连接和外连接

  • 内连接( 等值连接;非等值连接 ;自连接)
  • 外连接(左外连接;右外连接;全连接sqlserver数据库特有的)

内连接(INNER JOIN);
把满足了条件的两张表中的交集数据查询出来
语法:Select 结果 from 表1,表2 where 表1.column1 = 表2.column2
在这里插入图片描述


等值连接


两张表中有相同属性值的数据相等关联时


注意;在设计到多表查询时,要合理使用别名;使得查询精确,语法简洁;
在表名后定义别名即可

语法:

  • 1.inner join on
SELECT 查询结果 FROM1 INNER JOIN2 ON1的列=2同属性的列 (即查询条件);
  • 2.将查询条件写到where语句中
SELECT 查询结果 FROM1 ,2 WHERE1的列=2同属性的列 (即查询条件);

例如:查询学生的学号,姓名,性别,班级;;即学生对应自己的班级时

#例如;查询学生的学号,姓名,性别,班级;
SELECT
  s.stu_id,
  s.NAME,
  s.sex,
  g.class
FROM
  t_student s
  INNER JOIN t_grade g
    ON s.gra_id = g.id;

在这里插入图片描述


非等值连接


没有使用等值的属性作为查询条件.

案例演示:

首先在刚才的学生表新建加入一个成绩列,且插入分数数据;然后新建一个成绩分数表;

#成绩的区间表;
CREATE TABLE t_score(
             #成绩等级划分;
             Sconame VARCHAR(3),
             #成绩区间;
             max_score INT,
             min_score INT);
#插入数据;
INSERT INTO t_score(Sconame,max_score,min_score)
            VALUES('好耶',100,80),
                  ('一般般',79,61),
                  ('不行!',60,0);

查询学生的分数等级;

#查询
 SELECT
  s.stu_id,
  s.NAME,
  sco.Sconame
FROM
  t_student s
  INNER JOIN t_score sco
    ON s.score BETWEEN sco.min_score
    AND sco.max_score

在这里插入图片描述


自连接


在一张表中进行匹配连接查询.

案例,新建堡垒之夜角色关系表,且插入数据

#新建角色表;
 CREATE  TABLE t_fortnite(
                #编号;
                id INT ,
                #角色;
                person VARCHAR(8),
                #角色的上级编号;
                f_id INT);
#插入数据;
INSERT INTO t_fortnite(id,person,f_id)
            VALUES(1,'天狐',0),
                  (2,'夏日天狐',1),
                  (3,'香蕉特工',0),
                  (4,'西装香蕉',3),
                  (5,'夏日香蕉',3),
                  (6,'鱼干',0),
                  (7,'战术咸鱼',6),
                  (8,'超能咸鱼',7),
                  (9,'海王咸鱼',6),
                  (10,'咸鱼公主',6);

查询角色关系表:

#查询角色关系表;
SELECT * FROM t_fortnite f1 INNER JOIN t_fortnite f2 ON f1.f_id=f2.id;

在这里插入图片描述


左外连接(LEFT JOIN)


语法:

SELECT 查询结果 FROM1 LEFT JOIN2 ON1的列=2同属性的列 (即查询条件);

在这里插入图片描述

查询时以左边的表数据为主;无论条件是否满足;都会将左边数据查询出来.


案例:
先把学生表中 黑西装和天山狐妖的班级号设置为空值(即(NULL))

查询学生的学号,姓名,性别,班级;;即学生对应自己的班级时.

#左外连接;
SELECT
  s.stu_id,
  s.NAME,
  s.sex,
  g.class
FROM
  t_student s
  LEFT JOIN t_grade g
   ON s.gra_id = g.id;

即使有不满足查询条件的空值;仍然会显示.

在这里插入图片描述


右外连接(RIGHT JOIN )


语法:

SELECT 查询结果 FROM1 RIGHT JOIN2 ON1的列=2同属性的列 (即查询条件);

在这里插入图片描述

查询时以左边的表数据为主;无论条件是否满足;都会将右边数据查询出来.


查询学生的学号,姓名,性别,班级;;即学生对应自己的班级时.

SELECT
  s.stu_id,
  s.NAME,
  s.sex,
  g.class
FROM
  t_student s
  RIGHT JOIN t_grade g
   ON s.gra_id = g.id;

在这里插入图片描述



SQLyog 可视化工具进行数据库的备份以及还原


在数据库的使用过程中,为了防止数据被误删,应当提前做好备份.

在这里插入图片描述

数据库的备份;注意备份的是结构还是数据;以及存放的地址;方便后续使用

在这里插入图片描述

在数据库导入还原时,找到数据库的地址就行

在这里插入图片描述



以上是关于MySQL基础----[多表设计,数据库设计范式,内连接,外连接,数据库备份及导入还原 ]的主要内容,如果未能解决你的问题,请参考以下文章

MySQL数据库的多表关系设计范式及其备份和还原

MySQL数据库的多表关系设计范式及其备份和还原

MySQL 基础知识 三大范式

MySQL数据库基础-2范式

MYSQL学习之数据库设计三范式

Mysql的三范式设计