目录
一、数据库多表设计
1.数据库设计范式
(1)第一范式(确保每列保持原子性)
即数据库表中的所有字段值都是不可再分的原子值,这就满足了第一范式。例如学生表中的联系方式列表述并不明确,因为联系方式有多种。
(2)第二范式
第二范式就是要有主键(PRIMARY KEY),其他字段依赖于主键。因此也就有了唯一性。没有主键、失去唯一性,在集合中就无法定位到这行数据。
(3)第三范式
确保每列都和主键列直接相关,而不是间接相关。要去额一个数据库表中不包含已在其他表中包含的非主关键字信息。
2.外键
(1)定义:
引用另一个数据表的某条信息,外键必须与另一个表主键关联,类型一致。
数据表之间的关联/引用关系是依靠具体主键(PRIMARY KEY)和外键(FOREIGN KEY)建立起来的。我们以学生表为例
先建立一个专业表
CREATE TABLE major(
id INT PRIMARY KEY AUTO_INCREMENT, -- 专业id
NAME VARCHAR(10) NOT NULL -- 专业名称
)
(2)外键添加格式:
这时我们为学生表添加一个专业外键。
方法一:学生表未创建,直接在表里添加外键约束
create table student(
id int not null auto_increment primary key,
num int,
name varchar(10),
majorid int, -- 外键名称和类型,该类型应与其所在外键表列的类型相同
CONSTRAINT 约束名 foreign key(majorid ) references major(id)
);
-- 约束名命名规则:FK_外键表名_主键表命_On_外键名
方法二:学生表已经被创建,通过 ALTER 为表添加列
ALTER TABLE student ADD CONSTRAINT fk_student_major_on_majorid FOREIGN KEY(majorid ) REFERENCES major(id)
(3)根据两表关系选择外键位置
- 一对一关系
外键随便加在其中一个表中即可,建议加在查询频繁的表中。
-- 例如学生表和成绩表
-- 一个学生对应一个成绩,一个成绩也只属于一个学生
-- 成绩表
CREATE TABLE grade(
id int primary key aotu_increment,
grades int
)
-- 学生表
CREATE TABLE student(
num INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10) NOT NULL,
gender CHAR(1) NOT NULL,
gradeid int,
CONSTRAINT fk_grade_student_on_gradeid FOREIGN KEY(gradeid) REFERENCES grade(id)
)
- 一对多关系
外键添加在对应关系为多的表中
-- 例如学生表和专业表
-- 一个学生只能属于一个专业,一个专业可以有多个学生
-- 专业表
CREATE TABLE major(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10) NOT NULL
)
-- 学生表
CREATE TABLE student(
num INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10) NOT NULL,
gender CHAR(1) NOT NULL,
majorid int,
CONSTRAINT fk_major_student_on_majorid FOREIGN KEY(majorid) REFERENCES major(id)
)
- 多对多关系
此时应该新建第三个表,将两表外键放在这第三个表中
-- 例如学生表和课程表
-- 一个学生可以选多门课程,一门课程可以被多个学生选
-- 课程表
CREATE TABLE course(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10) NOT NULL
)
-- 学生选课表
CREATE TABLE student_course(
id INT PRIMARY KEY AUTO_INCREMENT,
student_num INT,
courseid INT,
CONSTRAINT fk_student_course_on_student_num FOREIGN KEY(student_num) REFERENCES
student(num),
CONSTRAINT fk_course_student_on_courseid FOREIGN KEY(courseid)REFERENCES course(id)
)
注:1、当主表中没有对应的记录时,不能将记录添加到从表
2、不能更改主表中的值而导致从表中的记录孤立
3、从表存在与主表对应的记录,不能从主表中删除该行
4、删除主表前,先删从表
二、关联查询
1.含义
又称多表查询,当查询的字段来自于多个表时,就会用到关联查询。
语法:Select 结果 from 表1,表2 where 表1.column1 = 表2.column2
平时查询过程中会引起 笛卡尔乘积现象:表1有m行,表2有n行,查询结果有m*n行。
这是因为没有进行有效的连接,这就需要我们为查询语句添加有效的连接
2.关联查询连接方式
-
内连接(inner join)
把满足条件的两张表的交集数据查询出来
语法:Select 结果 from 表1 inner join 表2 on 表1.column1 = 表2.column2
-- 建表过程见上述,这里不在重复
-- 查询学生学号、姓名、性别及其专业名称
SELECT
s.num,
s.name,
s.gender,
m.name
FROM student s INNER JOIN major m ON s.majorid = m.id
-
左外连接(left join)
显示表一所有部分,表一表二相交部分
语法:select 结果 from 表1 left join 表2 on 表1.column1 = 表2.column2
-- 查询学生专业信息
SELECT *FROM student s LEFT JOIN major m ON s.majorid = m.id
-
右外连接(right join)
显示表二所有部分,表一表二相交部分
语法:select 结果 from 表1 right join 表2 on 表1.column1 = 表2.column2
-- 统计每个专业人数
SELECT COUNT(s.num)COUNT,m.name
FROM student s RIGHT JOIN major m
ON s.majorid = m.id
GROUP BY m.name
三、子查询(嵌套查询)
1.含义
出现在其他语句中的select语句,称为子查询或内查询;外部的查询语句,称为主查询或外询。
2.分类
-
按子查询出现的位置:
-- from后面:支持表子查询(结果集一般为多行多列)
-- 查询重名的学生信息(表子查询)
SELECT *FROM (SELECT s.name,COUNT(*)c FROM student s GROUP BY s.name)sc WHERE sc.c>1
-- where:支持标量子查询(结果集只有一行一列),列子查询(结果集只有一列多行)
-- 查身高最高的(标量子查询)
SELECT * FROM student WHERE height = (SELECT MAX(height) FROM student)
-- 查身高等于165 和 175的学生(列子查询)
SELECT *FROM student WHERE height IN (SELECT height FROM student WHERE height = 1.65 OR height = 1.75)
-
按功能、结果集的行列数不同:
标量子查询(结果集只有一行一列)
-- 查身高最高的(标量子查询)
SELECT * FROM student WHERE height = (SELECT MAX(height) FROM student)
列子查询(结果集只有一列多行)
-- 查身高大于平均身高
SELECT *FROM student WHERE height>(SELECT AVG(height) FROM student)
表子查询(结果集一般为多行多列)
-- 查重名的(表子查询)
SELECT *FROM (SELECT s.name,COUNT(*)c FROM student s GROUP BY s.name)sc WHERE sc.c>1
有关数据库多表设计和关联查询的知识到这里就结束了,希望能给大家带来帮助。如有不正,恳请及时指出,让我们共同学习、共同进步!