MySQL多表关联查询

本文详细解释了SQL中的连接查询,包括等值连接、内连接、外连接以及一对一和一对多关系的表设计,通过实例演示了如何使用外键约束和不同类型的连接操作。
摘要由CSDN通过智能技术生成

外键(foreign key)

外键的定义:
    [constraint 约束名称] foreign key(作为外键的字段名) references 父表名称(父表主键)
      [on delete cascade]  [on update cascade];
外键的作用:用来约束子表中的记录,使之与父表的记录对应

连接查询

等值连接:select 字段1,字段2,... from 表A,表B where 连接条件 [其他过滤条件];
内连接: select 字段1,字段2,... from 表A inner join 表B   on 连接条件[其他过滤条件];
      等值连接与内连接的效果是一样的,都是查询出符合连接条件的记录
外连接:
     左外连接: select 字段1,字段2,... from 表A  left join 表B   on 连接条件;
     注意:左外连接的查询结果是,除了返回表中符合条件的记录外还要加上左表中剩下的全部记录。
     右外连接: select 字段1,字段2,... from 表A right join 表B on 连接条件;
     注意:右外连接的查询结果是,除了返回表中符合条件的记录外还要加上右表中剩下的全部记录。

“一对多”关系表设计

“一对多”关系:第一个表中的单个行可以与第二个表中的一个或多个行关联,但第二个表中的一个行只可以与第一个表中的一个行关联。 例如:学校表(school)与学生表(student)。学校表(school)中的一条记录可以对应学生表(student)中的多条记录;学生表(student)中的一条记录只能对应学校表(school)的一条记录。
设计思路:通过在子表(“多”的一方)上设置外键的方式,关联父表( “一”的一方)的主键。这样,父表的一条记录就可以关联子表的n条记录了。 

#一对多关系演示
先创建“父表”(“一”方)
create table school(
   schoolid    int  auto_increment primary key,
   name   varchar(20) not null,
   introduce   text
);

插入一些学校记录数据
insert into school(name,introduce)values('清华大学','清华大学非常好');
insert into school(name,introduce)values('北京大学','北京大学也不错');
insert into school(name,introduce)values('西安邮电大学',null);

再创建“子表”(“多”方)
create table student(
   stuid   int  auto_increment primary key,
   name   varchar(20) not null,
   score  double not null,
   school_id  int,
   foreign key(school_id) references school(schoolid) 
    on delete cascade  on update cascade
);

插入一些学生记录数据
insert into student(name,score,school_id)values('张三',90,8);
insert into student(name,score,school_id)values('李四',93,9);
insert into student(name,score,school_id)values('王五',96,8);
insert into student(name,score,school_id)values('赵六',96,9);



等值连接查询
查找每个学生的姓名、成绩、所在学校的名称
SELECT stu.`name`,stu.`score`,sc.`name`  FROM school sc,student stu WHERE stu.`school_id`=sc.`schoolid`;
查找王五的姓名、成绩、所在学校的名称
SELECT stu.`name`,stu.`score`,sc.`name`  FROM school sc,student stu WHERE stu.`school_id`=sc.`schoolid` AND stu.`name`='王五';

内连接查询
SELECT stu.`name`,stu.`score`,sc.`name`  FROM school sc INNER JOIN student stu ON stu.`school_id`=sc.`schoolid` AND stu.`name`='王五';

左外连接查询
SELECT stu.`name`,stu.`score`,sc.`name`  FROM school sc LEFT JOIN student stu ON stu.`school_id`=sc.`schoolid` ;

右外连接查询
SELECT stu.`name`,stu.`score`,sc.`name`  FROM school sc RIGHT JOIN student stu ON stu.`school_id`=sc.`schoolid` ;

“多对多”关系表设计

“多对多”关系:第一个表中的一个行可以与第二个表中的一个或多个行关联。第二个表中的一个行也可以与第一个表中的一个或多个行关联。
 设计思路:通过设置中间表的方式实现“多对多”关系表的设计。中间表至少有两个外键字段,分别关联于两张“多”表的主键,而且这两个外键字段的组合值不能重复(可以通过将这两个字段设置为联合主键,以确保它们的组合值不重复)。

多对多关系:成员表(members)与社团表(community)

# 创建members表
create table members(
   mid   int  auto_increment primary key,
   name   varchar(20) not null,
   sex    char(2)
);

# 插入成员信息
insert into members(name,sex)values('郭靖','男');
insert into members(name,sex)values('杨过','男');
insert into members(name,sex)values('黄蓉','女');
insert into members(name,sex)values('小龙女','女');

# 创建社团表
create table community(
   cid   int  auto_increment primary key,
   name   varchar(20) not null,
   introduce text
);

# 插入社团信息
insert into community(name,introduce)values('街舞社团','喜欢跳舞的可以加入');
insert into community(name,introduce)values('武术社团','爱好武术的团体社团');
insert into community(name,introduce)values('吉他社团','Guitar lover...');


# 设置中间关联表
create table members_community(
   members_id  int,
   community_id  int,
   joindate  date,
   foreign key(members_id) references members(mid),
   foreign key(community_id) references community(cid),
   primary key(members_id,community_id)
);

# 插入中间表信息(设置关联)
insert into members_community(members_id,community_id,joindate)
       values(1,2,'2024-01-01'),(2,2,'2024-01-02'),
       (2,3,'2024-01-03'),(3,1,'2024-02-02'),
       (3,2,'2024-02-08'),(3,3,'2024-02-22');

# 查询成员姓名与成员参加的社团名称、加入社团时间
select   m.name 成员姓名,c.name 参加的社团,mc.joindate 加入日期
                                from members m 
                                inner join
                                members_community mc
                                on m.mid=mc.members_id
                inner join
                community c
							 on mc.community_id=c.cid;

“一对一”关系表设计

“一对一”关系:第一个表中的单个行只可以与第二个表中的一个行关联,且第二个表中的一个行也只可以与第一个表中的一个行关联。
 设计思路:
基于“唯一外键”的设计:“一对一”关系表通过在某一方表中设置“唯一外键”的方式来实现。
基于“将主键同时作为外键的方式”设计: “一对一”关系表也可以通过将某张表的主键作为外键关联另一张表的方式来实现。 

一对一关系

创建person表(“一”方的父表)
create table person(
   pid  int auto_increment primary key,
   name   varchar(20),
   sex char(2)
);

insert into person(name,sex)values('张三','男'),('李四','男');


基于“唯一外键”的设计:创建card身份证表(“一”方的子表)
create table card(
   cid  int auto_increment primary key,
   cnum   varchar(20) not null unique,
   person_id  int unique,
   foreign key(person_id) references person(pid)
);

insert into card(cnum,person_id)values('zs123',1),('ls456',2);

# 查询'张三'的身份证号
select  person.name,card.cnum    from person 
           inner join card 
           on person.pid=card.person_id and person.name='张三';

# 基于“将主键同时作为外键的方式”设计
create table card(
   cid  int  primary key,
   cnum   varchar(20) not null unique,
   foreign key(cid) references person(pid)
);

insert into card(cid,cnum)values(1,'zs123'),(2,'ls456');

练习题:

科目表:
CREATE TABLE SUBJECT(
   subid   INT  AUTO_INCREMENT PRIMARY KEY,
   subname  VARCHAR(20)  NOT NULL  
);

中间表:
CREATE TABLE student_subject(
   student_id   INT,
   subject_id   INT,
   FOREIGN KEY(student_id) REFERENCES student(stuid),
   FOREIGN KEY(subject_id) REFERENCES SUBJECT(subid),
   PRIMARY KEY(student_id,subject_id)
);


INSERT INTO student(NAME,score)VALUES('郭靖',60),('黄蓉',65),('欧阳锋',92);
INSERT INTO SUBJECT(subname)VALUES('物理'),('化学'),('数学'),('英语');
INSERT INTO student_subject(student_id,subject_id)VALUES(1,1),(1,3),(2,3),
  (2,4);
  
  问题:
学号为2的学生选择了哪些课程?

SELECT stu.name 姓名,sub.subname 课程 FROM student stu 
INNER JOIN student_subject sc ON stu.stuid=sc.student_id 
INNER JOIN SUBJECT sub ON sc.subject_id=sub.subid;

以上内容如有错误请批评指正。

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值