6

我的应用程序将大量来自数据库的数据加载到复杂的数据结构中。在内存中的数据结构ressembles的数据库的结构,这意味着,如果该数据库包含以下表:外键的循环依赖:使用它还是避免它?

  • 表A,关键是A1
  • 表B,关键是B1,其中一列是一个外键表[中的关键]甲
  • 表C,关键是C1,列中的一个是外键[关键表B

然后,我有类A, B和C,以及:

  • B(B :: M_A)的数据成员是一个指向
  • Ç(C :: M_B)的数据成员是一个指针到B

这意味着,如果我负荷数据库,我必须以正确的顺序加载它。如果我第一次加载C,那么它会抱怨它不能设置值C :: m_b,因为它指向的实例没有加载。

问题是,当有语言中也有一列是一个外键的其他表之一,让我们说C.

我可以通过加载所有外键作为字符串解决问题,然后执行在所有数据加载完毕后进行查找,但由于我有时需要加载数百万条记录,所以我无法承担在这些(尽管是临时)字符串上的内存消耗。

在阅读过有关优秀设计(例如“大规模C++软件设计”一书)的文章之后,我认为根本不需要循环引用。 例如如果文件X.H包含Y.H,但是Y.H也包含X.H,则可能是设计不好;如果X类依赖于Y类,反之亦然,你可能会有一个糟糕的设计,应该通过提取这个依赖关系并引入一个依赖于X和Y的第三类Z来解决(X和Y不再依赖于对方) 。

将此设计规则扩展到数据库设计是一个好主意吗?换句话说:防止外键中的循环引用。

回答

3

您应该只需要一个循环引用的时候就是在创建分层结构时,比如组织树。

Table Employees 
    EmployeeID <----------| 
    SupervisorEmployeeID ---| 
2

是的,数据库中的周期性依赖关系是重新考虑设计的良好借口。

+0

为什么?你没有为你的断言提供理由。 – cdmckay 2017-09-26 01:58:43

4

从数据建模的角度来看,circualr依赖关系没有什么根本的“错误”。这并不意味着该模型是错误的。

不幸的是,大多数SQL DBMS不能有效地实现这样的约束,因为它们不支持多表更新。通常,解决这个问题的唯一方法是暂时暂停一个或多个约束(例如使用“可推迟的”外键或类似功能),或者通过更改模型使约束的某些部分可选(将其中一个引用列放入新表)。这只是SQL的讨厌限制的一个解决方法,但是,这并不意味着你开始时做了任何错误。

2

您必须对您拥有的数据建模。如果数据中存在循环关系(例如,每张照片属于一个文件夹;但每个文件夹都有一张封面照片),那么将其建模为数据库中的循环关系是正确的。

我在使用Oracle时只有这种情况,所以我没有机会查看如何在其他数据库上实现这种关系。但对于Oracle,您可以在这里阅读我的文章:

http://www.databasesandlife.com/circular-dependencies-on-foreign-key-constraints-oracle/