数据库建表时一定要设置外键约束关系吗?

我们都知道每张数据表都有一个能够确定每行数据唯一性的字段,也就是主键。而在关系数据库中,常常有两表存在一定关系的情况。即一张表的主键跟另一张的外键存在…
关注者
49
被浏览
47,301

11 个回答

以下段落摘自 用Angular和NodeJS开发真正的CRUD应用

问题2 :是否应将服务端校验尽可能嵌入到数据模型中?我的答案是:“否”。我知道这一次的回答更具争议。众所周知,数据库提供了一些数据一致性检查的功能,例如主键检查和外键检查。为什么不利用这些功能呢? 我的经验告诉我,数据模型在诞生时并不完美,它们在生命周期内经常被调整。这就意味着数据模型中添加的业务逻辑越多,调整它们的成本将会越高。想象一下,您要调整一个外键所要付出的数据转换成本。而如果将这种校验逻辑与数据模型分开,则可以在调整模型时获得更大的灵活性。我并不是建议您完全不用它们,只是建议要三思。

有人担心不设置外键约束会最终导致数据不一致,而我认为问题的本质是错误的数据模型设计。我就举一个回答中的例子:销售订单表和商品表设立了外键约束,即要求录入销售订单的时候,利用外键约束来检查商品是否存在。注意,这个外键的约束也仅仅是在录入订单的时候起到了检查作用,而在其他方面会添加麻烦。例如,我想归档某个商品(已经不生产了), 那我就必须要同时归档销售订单。而我又不想删除销售订单,因为我还想做一些销售历史分析。请问这时候该怎么办?

这里涉及的问题是两个实体,还是单个实体?有许多人把数据库的一个表说成是“实体”,这在业务建模中是错误的。实体是表之上的一种抽象,一种实体可以包含多个表的。以上面的例子,销售订单和商品是两个实体,这意味着一个实体的消亡不会影响另一个。这个时候你就不应该在销售订单上加商品的外键约束,商品对销售订单来说只是个属性。而如果是单个实体的情况,例如销售订单抬头表和行项目表,那么在行项目表上设置销售订单号的外键约束就合理了,因为行项目不能独立于抬头存在,要死一起死。

基于以上模型设计的梳理,我相信也不存在分表分库的问题。因为无论如何不能将属于一个实体的表和属性分开的,它已经是一个原子了。

最后,如果利用了外键约束来防止添加或删除动作导致的数据不一致,应用开发是否能节省成本?回答是“NO”。因为数据库只会返回这样的错误文本“Foreign key constrain error!”。你好意思直接将这个文本抛给用户?

外键的存在是有意义的,例如一个人的基本信息和工资分别存放一张表。

如果有一天,你发现一个找不到基本信息的人,却有工资信息,问题就出现了。