发表于: 2020-12-26 23:05:18

2 1395


今天完成的事情:
了解一对一,一对多,多对多
主键和外键+索引
理清实体表和关系表
明天计划的事情:
数据库设计
接口文档
遇到的问题:
以下
收获:
一对多

一个班级对应多个学生,这个在数据库怎么设计?在IDEA中mapper.xml怎么设计sql语句,用什么把这些表关联起来?




一对一
一个班级只能有一个班主任,




多对多


比如大学生,一个人可以选择多个课程,而一个课程有多名学生
拿美团炸鸡店的炸鸡套餐举例,一个人可以选择多个炸鸡套餐,而一个炸鸡套餐可以被很多人选择。

这些一对一,一对多,多对多是通过主键和外键来协调的。


如何协调?

主键之前用过,就是有一列数据被设置成主键之后,这一列的不能重复,为了方便查找,能够准确的定位信息,一般设置ID等等,唯一性的数据设置成主键


但需要修改的数据一般不设置主键,比如身份证号、手机号、邮箱地址,因为主键是来定位数据的,一个人修改主键数据之后,就查不到这个人了。


作为主键最好是完全业务无关的字段,我们一般把这个字段命名为id。常见的可作为id字段的类型有:


自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键重复,也不用自己预先生成主键;


全局唯一GUID类型:使用一种全局唯一的字符串作为主键,类似8f55d96b-8acc-4636-8cb8-76bf8abc2f57。GUID算法通过网卡MAC地址、时间戳和随机数保证任意计算机在任意时间生成的字符串都是不同的,大部分编程语言都内置了GUID算法,可以自己预算出主键。


对于大部分应用来说,通常自增类型的主键就能满足需求。我们在students表中定义的主键也是BIGINT NOT NULL AUTO_INCREMENT类型。



联合主键

关系数据库实际上还允许通过多个字段唯一标识记录,即两个或更多的字段都设置为主键,这种主键被称为联合主键。


对于联合主键,允许一列有重复,只要不是所有主键列都重复即可。

一般不进行设置



外键


是为了解决如何将两张表关系起来?



通过class_id使students和classes关系起来,这就被成为外键


但外键并不是通过列名实现的,而是通过定义外键约束实现的:


ALTER TABLE students
ADD CONSTRAINT fk_class_id
FOREIGN KEY (class_id)
REFERENCES classes (id);



其中,外键约束的名称fk_class_id可以任意,FOREIGN KEY (class_id)指定了class_id作为外键,REFERENCES classes (id)指定了这个外键将关联到classes表的id列(即classes表的主键)。



建立外键约束


发现没有外键,原来是之前为了添加200百万数据改成了MyISAM,而MyISAM不支持事务处理与外键和行级锁



改了my.ini之后一定在服务上重启MySQL,不然引擎不会换过来的,找了好久,才想到了



服务



成功切换过来



================================
成功建立外键



其中,外键约束的名称fk_class_id可以任意,FOREIGN KEY (class_id)指定了class_id作为外键,REFERENCES classes (id)指定了这个外键将关联到classes表的id列(即classes表的主键)


====================================
多对多

通过一个中间表来建立关系



=====================


一对一


一个表的记录对应到另一个表的唯一一个记录
注意是表对表
students表的每个学生可以有自己的联系方式,如果把联系方式存入另一个表contacts,我们就可以得到一个“一对一”关系:

id
student_id
mobile
1
1
135xxxx6300
2
2
138xxxx2209
3
5
139xxxx8086

为啥不给students表增加一个mobile列?


如果业务允许,完全可以把两个表合为一个表。但是,有些时候,如果某个学生没有手机号,那么,contacts表就不存在对应的记录。实际上,一对一关系准确地说,是contacts表一对一对应students表。


还有一些应用会把一个大表拆成两个一对一的表,目的是把经常读取和不经常读取的字段分开,以获得更高的性能。例如,把一个大的用户表分拆为用户基本信息表user_info和用户详细信息表user_profiles,大部分时候,只需要查询user_info表,并不需要查询user_profiles表,这样就提高了查询速度。


总结:外键的目的是什么?为了和其他表建立一对多、多对多和一对一的关系,至少要有两张表


那么查找语句该怎么写?


1、内连接:只列出匹配的记录
这是一对多,一个班级可以有多名学生
SELECT s.name,c.name FROM students s,classes c WHERE s.class_id=c.id;

查询的是name,查询的表是students s,classes c,条件是s.class_id=c.id(这个进行外键约束)


班级的主键绑定了学生的外键





2、外连接:


外连接分类:
左外连接(LEFT [OUTER] JOIN)
右外连接(RIGHT [OUTER] JOIN)

全外连接(FULL [OUTER] JOIN)  注:MySQL5.1的版本暂不支持


2、1左外连接:左表列出全部,右表只列出匹配的记录。



2、2右外连接:右表列出全部,左表只列出匹配的记录。


3、交叉连接:

4、自连接:参与连接的表都是同一张表。(通过给表取别名虚拟出两张表)

注:非常重要,在JavaWeb中的目录树中用的特别多。
举例:查询出学生姓名和优秀学员的姓名(类似于求节点及其父节点)


详细解释一下上面的代码。对于同一张sutdents表,我们把s1作为学生表,s2作为优秀学员表。首先把全部的学生列出来(基于左外连接),然后找到我们所需要的条件:学生中优秀学员id(s1.excellent_student)等于学生的id(s2.id)。


我不知道这样这样查询的意义是什么?因为excellent_student是要自己填写的,而且要和id值一样,改起来比较麻烦,所以我觉得这样很沙雕

看这个看了半天,然后发觉就是这个东西,不懂为什么重要



举例:查询出所有优秀学员的姓名。



查询所有



==========================

索引


之前在查询200百万中数据中建立过,建立需要半个小时,好像建立结束就7个G的大小了。后来都删除了。不过查询速度提升很大,从几分钟到几秒


实体表和关系表


实体表就是对应实际对象的表,而关系表不代表一个对象,而是代表对象间的关系。
比如说这里有用户、用户角色,我们要实现一个用户对应多个角色,怎么办,首先我们有“用户表”和“用户角色”两个实体表,但是如何实现将两个实体表建立起一对多的关系,我们还需要另外一张表,专门存放用户表的ID和用户角色ID,这个表只是为了将两个实体表进行关联,也就是关系表。
那说白了就是存在于多对多






返回列表 返回列表
评论

    分享到