当前位置: 首页 > news >正文

MySQL之关系

目录

  • 关系
    • 多对多的关系,如何通过mysql来表示
    • 一对一关系

关系

多对多的关系,如何通过mysql来表示

站在老师的角度

一个老师可以教多个学生,

一个老师也可以教一个学生。

站在学生的角度

一个学生可以被一个老师教

一个学生也可以被多个老师教

结论:如果站在两边看都是一对多的情况,那么这个关系就是多对多的。
问题:

如果表示a老师教过x学生和y学生,x学生和y学生同时也被b老师教

解决方法

多对多关系,无论是把外键放在哪一张表都不合适,因为可能有多个值

解决方案:建立一个中间的关系表

create table student(
    id int primary key auto_increment,
    name char(10)
) charset utf8;

create table teacher(
    id int primary key auto_increment,
    name char(10)
) charset utf8;

create table t_s_r(
    id int primary key auto_increment,
    t_id int,
    s_id int,
    foreign key(t_id) references teacher(id),
    foreign key(s_id) references student(id)
) charset utf8 ;

insert into teacher values(null,"bgon"),(null,"nike");


insert into student values(null,"老王"),(null,"老李");

# 老王被bgon教过
insert into t_s_r values(null,1,1);

# nike教过老李
insert into t_s_r values(null,2,2);

# nike教过老王
insert into t_s_r values(null,2,1);


# 现在已知老师名称为bgon,请找出他教过的那些学生
mysql> select id from teacher where name="bgon";
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select s_id from t_s_r where t_id=1;
+------+
| s_id |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select name from student where id=1;
+--------+
| name   |
+--------+
| 老王   |
+--------+
# 子查询
mysql> select name from student where id=(select s_id from t_s_r where t_id=(select id from teacher where name="bgon"));
+--------+
| name   |
+--------+
| 老王   |
+--------+
1 row in set (0.00 sec)




# 已知学生名为老李,请查询出哪些老师教过他.
mysql> select id from student where name = "老李";
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)

mysql> select t_id from t_s_r where s_id=2;
+------+
| t_id |
+------+
|    2 |
+------+
1 row in set (0.00 sec)

mysql> select name from teacher where id=2;
+------+
| name |
+------+
| nike |
+------+
1 row in set (0.00 sec)

# 子查询 
mysql> select name from teacher where id=(select t_id from t_s_r where s_id=(select id from student where name = "老李"));
+------+
| name |
+------+
| nike |
+------+
1 row in set (0.00 sec)
总结:
  1. 如何确认多对多的关系?

    站在两个表的角度去想

  2. 处理方式,通过在两个表中间建立一个外键表,该外键表分别都关联两表的字段。

联合唯一约束

对于上面的t_s_r表进行改进
# 原表
create table t_s_r(
    id int primary key auto_increment,
    t_id int,
    s_id int,
    foreign key(t_id) references teacher(id),
    foreign key(s_id) references student(id),
) charset utf8 ;

# 改进方法一(表已创建的情况下):unique key
alter table t_s_r add unique key(t_id,s_id);

# 改进方法二(表没创建的情况下):unique key
create table t_s_r(
    id int primary key auto_increment,
    t_id int,
    s_id int,
    foreign key(t_id) references teacher(id),
    foreign key(s_id) references student(id),
    unique key(t_id,s_id)
) charset utf8 ;



# 联合主键
create table t_s_r(
    id int primary key auto_increment,
    t_id int,
    s_id int,
    foreign key(t_id) references teacher(id),
    foreign key(s_id) references student(id),
    primary key(t_id,s_id)
) charset utf8 ;
对于上面的t_s_r表进行改进------最终版
# 创建学生表
create table student(
    id int primary key auto_increment,
    name char(10)
) charset utf8;

# 创建教师表
create table teacher(
    id int primary key auto_increment,
    name char(10)
) charset utf8;

# 创建学生和老师关系表
create table t_s_r(
    t_id int,
    s_id int,
    foreign key(t_id) references teacher(id),
    foreign key(s_id) references student(id),
    primary key(t_id,s_id)
) charset utf8 ;

insert into teacher values(null,"bgon"),(null,"nike");

insert into student values(null,"老王"),(null,"老李");

# 老王被bgon教过
insert into t_s_r values(null,1,1);

# nike教过老李
insert into t_s_r values(null,2,2);

# nike教过老王
insert into t_s_r values(null,2,1);


# 问题:现在已知老师名称为bgon,请找出他教过的那些学生
mysql> select id from teacher where name="bgon";
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select s_id from t_s_r where t_id=1;
+------+
| s_id |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select name from student where id=1;
+--------+
| name   |
+--------+
| 老王   |
+--------+
# 整合查询语句:子查询
mysql> select name from student where id=(select s_id from t_s_r where t_id=(select id from teacher where name="bgon"));
+--------+
| name   |
+--------+
| 老王   |
+--------+
1 row in set (0.00 sec)




# 问题:已知学生名为老李,请查询出哪些老师教过他.
mysql> select id from student where name = "老李";
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)

mysql> select t_id from t_s_r where s_id=2;
+------+
| t_id |
+------+
|    2 |
+------+
1 row in set (0.00 sec)

mysql> select name from teacher where id=2;
+------+
| name |
+------+
| nike |
+------+
1 row in set (0.00 sec)

# 整合查询语句:子查询 
mysql> select name from teacher where id=(select t_id from t_s_r where s_id=(select id from student where name = "老李"));
+------+
| name |
+------+
| nike |
+------+
1 row in set (0.00 sec)

一对一关系

例如:每一个人都有一个身份证。一个身份证只对应一个人

分表:
  1. 垂直分表,例如:人物的详细信息,就可以垂直分表

    # 全表
    create table person(
     id int primary key auto_increment,
     name char(10),
        age int,
     height float,
        weigth float
    )
    
    # 垂直分表:person
    create table person(
        id int primary key auto_increment,
     name char(10),
        age int
    ) charset utf8;
    
    
    # 垂直分表:person_info
    create table person_info(
     id int primary key,
        height float,
        weigth float,
     foreign key(id) references person(id)
    ) charset utf8;
  2. 水平分表

    数据量很大,使用一个表,查询效率低,使用两个表来存取这些数据

处理一对一关系处理方式:
  1. 先确定先后顺序

  2. 将先存在的数据作为主表

  3. 后存在的作为从表

  4. 使两个表的id保持一一对应

    方法1:从表的id即是主键又是外键

    方法2:从表的id设置为外键,并保证唯一

人物关系表,从客户演变为学生:

# 创建客户表
create table kehu_t(
    id int primary key auto_increment,
    name char(10),
    phone char(11)
)

# 创建学生表
create table student_t(
    id int primary key auto_increment,
    card_id char(18)
)
为什么要分表:
  1. 数据分担在多个表,提高了查询的效率

转载于:https://www.cnblogs.com/plf-Jack/p/11177727.html

相关文章:

  • LipSync Pro插件
  • 处理 ubuntu preseed 过程中 /etc/network/interfaces 被覆盖问题
  • Destroying assets is not permitted to avoid data loss.
  • apache 的连接限制配置
  • IDEA下指定MAVEN项目中的编译版本
  • 社会学百科——英国DK出版社
  • 安装错误1625:系统策略禁止这个安装,请与系统管理员联系。
  • 苏东坡新传——李一冰著
  • 企业经济性裁减人员规定——劳动合同法小全书
  • 解决firefox下div的background无效的问题
  • 中国古代智谋故事大观
  • (javascript)再说document.body.scrollTop的使用问题
  • 司马相如和卓文君——野史+臆想
  • 沧海遗珠——狄仁杰
  • (Ruby)Ubuntu12.04安装Rails环境
  • 【Leetcode】101. 对称二叉树
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • C语言笔记(第一章:C语言编程)
  • go语言学习初探(一)
  • node.js
  • python学习笔记 - ThreadLocal
  • React-生命周期杂记
  • sessionStorage和localStorage
  • 翻译--Thinking in React
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 使用common-codec进行md5加密
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 学习笔记TF060:图像语音结合,看图说话
  • 一个完整Java Web项目背后的密码
  • 栈实现走出迷宫(C++)
  • 树莓派用上kodexplorer也能玩成私有网盘
  • #if和#ifdef区别
  • (09)Hive——CTE 公共表达式
  • (10)STL算法之搜索(二) 二分查找
  • (7) cmake 编译C++程序(二)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (一)为什么要选择C++
  • (转)shell调试方法
  • *** 2003
  • **CentOS7安装Maven**
  • .net CHARTING图表控件下载地址
  • .NET Core 发展历程和版本迭代
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .net中生成excel后调整宽度
  • .pyc文件是什么?
  • @JoinTable会自动删除关联表的数据
  • [20190416]完善shared latch测试脚本2.txt
  • [240527] 谷歌 CEO 承认 AI 编造虚假信息问题难解(此文使用 @gemini 命令二次创作)| ICQ 停止运作