关系数据库设计中,用中间表好还是直接设定主外键关联好?

简介: 有人会对数据库有这样的疑问:因为大多数的数据库教程上都是告诉你关系数据库如何去创建1:1、1:N和N:M的数据库关系,但我发现很多开源产品中,并没有直接使用关系数据库的关系查询、关系删除等功能,而是直接在代码中对多个表的查询结果进行组合。

有人会对数据库有这样的疑问:

因为大多数的数据库教程上都是告诉你关系数据库如何去创建1:1、1:N和N:M的数据库关系,但我发现很多开源产品中,并没有直接使用关系数据库的关系查询、关系删除等功能,而是直接在代码中对多个表的查询结果进行组合。

这两种方式的优缺点是什么呢?为什么很多项目都选择后者呢?在一个中型以上的项目实践中,我该选择哪种方式,或是两种方式结合使用?


我想:

1,数据表与数据表之间有关联(Relationship)是肯定的,但是不一定要用外键(Foreign Key),为什么?外键本质是一种约束(Constraint),该约束决定了你在增删改查的时候都会有额外开销。【实际上数据库在处理外键的时候估计也是创建一个中间表根据中间表来做关联操作,完成后再删除】

2,“对于 “N对N” 的关系,两个 Model 之间肯定是需要一张中间表的,比如 Student、Class 之间选课关系,是多对多的,肯定需要一张 Enroll 的表来维持,记录两个表的主键(Primary Key),但是不需要在数据库层加外键约束,只需要加两个索引,或作为联合主键。

3,至于查询,尽量不用 JOIN。但是问题是我确确实实是需要知道多个表的信息。
比如我要知道某门课(Class,已知 ID)的信息,同时还有选上该课(Enrolled)的学生信息(Student)。
使用 JOIN ?没问题,我相信你可以写出一个很长的 JOIN 语句。
但是,可能有的地方大概这样实现的(伪代码):

 
 
  1. getClassInfo(@class_id)
  2. { SELECT class_col1, class_col2 FROM class WHERE class.id = @class_id }
  3. getStudentInfo(@class_id)
  4. { SELECT student_col1, student_col2 FROM student WHERE student.id IN (SELECT enroll.student_id FROM enroll WHERE enroll.class_id = @class_id) }

两种方案各有优缺。
后者最大的一个优点是灵活,比如我们引入缓存(Caching)。
一般来说,一个学校 class 数量不多,并且经常被查询,系统可能会引入缓存层(如 memcached、redis)来存放 class 对象。
那么上面的 getClassInfo 其实会变为

   
 
  1. {
  2.   if(memcached.has(@class_id) != null)
  3.   {
  4.       return memcached.get(@class_id);
  5.   }
  6.  
  7.   //查询数据库(只有 class 表),和上面的 SQL 一样
  8.   memcached.set(@class_id, class_object);
  9.   return class_object;
  10. }

相关文章
|
5月前
|
数据库
t0`通常指的是主表名
t0`通常指的是主表名
41 0
|
存储 关系型数据库 MySQL
MySQL数据库约束与表的设计
本文主要介绍MySQL数据库中一些常用的约束,以及表的设计方法。
109 0
MySQL数据库约束与表的设计
|
存储 SQL Java
Mysql数据库表字段设计优化(状态列)
初始状态码(java int 32 long 64),int 可以表示31种(除去0000),long可以表示63种(除去0000),当然不可能将0000赋值给初始状态,一般来讲,选择int还是long是根据具体业务需求来决定的。
393 0
Mysql数据库表字段设计优化(状态列)
|
关系型数据库 MySQL 数据库
MySQL数据库(14):表关系
MySQL数据库(14):表关系
|
SQL 关系型数据库 MySQL
MySQL - 数据库设计(表之间的 3 种关联关系)
MySQL - 数据库设计(表之间的 3 种关联关系)
705 0
MySQL - 数据库设计(表之间的 3 种关联关系)
|
Web App开发 API 数据库
零代码实现一对一表关系和无限主子表级联保存
本文主要介绍一对一关系和无限主子表在crudapi系统中的应用。一对一关系是指关系数据库中两个表之间的一种关系。关系数据库中第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关。
253 0
零代码实现一对一表关系和无限主子表级联保存
|
开发工具
关于表变动而导致的实体变动问题
因为表变动而导致的实体变动问题,出现这种情况较多的是版本迭代的时候。 项目开发初期,表变动导致的代码改动量相对较小,改动后出现的问题也比较少。而在项目迭代的过程中,因为项目已经成型,大部分代码的逻辑和用法都已固定。
5824 0
|
数据库
【自然框架】元数据的数据库结构的详细说明和示例(三):项目与数据库字段的关联
【自然框架】PowerDesigner 格式的元数据的表结构 【自然框架】元数据的数据库结构的详细说明和示例(一):项目描述部分 【自然框架】元数据的数据库结构的详细说明和示例(二):数据库描述部分     1、Manage_FunListCol(列表用字段) 字段名...
944 0
|
SQL 数据库 关系型数据库
EFCore中如何移除主外键关系
目录 EFCore中如何移除主外键关系 场景介绍 主外键关系的问题 解决思路 禁止级联关系的生成 MicroFX.EntityFrameworkCore.RemoveForeignKey扩展 EFCore中如何移除主外键关系 场景介绍 我用EFCore写了一个blog程序,我要通过写文章来分享自己的知识,我定义了一个Article用来存放文章信息,我还定义了一个Category用来存放文章的分类,Category与Article是一对的关系。
3593 0
|
Java 数据库
不设外键:用程序来实现表之间的关联
Association 相信有很多同学都有使用过Hibernate框架的开发经验,尽管现在开发人员对Hibernate的褒贬不一,我们暂且不谈这个话题。
1706 1