MySQL数据库基础——多表设计_关联查询

目录

一、数据库多表设计

1.数据库设计范式

(1)第一范式(确保每列保持原子性)

(2)第二范式

(3)第三范式

2.外键

   (1)定义:

   (2)外键添加格式: 

   (3)根据两表关系选择外键位置

二、关联查询

1.含义

2.关联查询连接方式

内连接(inner join)

左外连接(left join)

右外连接(right join)

三、子查询(嵌套查询)

1.含义

2.分类


一、数据库多表设计

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

       有关数据库多表设计和关联查询的知识到这里就结束了,希望能给大家带来帮助。如有不正,恳请及时指出,让我们共同学习、共同进步!

猜你喜欢

转载自blog.csdn.net/2301_78341216/article/details/139199789