8

我的应用程序将大量数据从数据库加载到复杂的数据结构中。内存数据结构类似于数据库的结构,这意味着如果数据库包含以下表:

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

然后我有 A、B 和 C 类,并且:

  • B (B::m_a) 的数据成员是指向 A 的指针
  • C (C::m_b) 的数据成员是指向 B 的指针

这意味着如果我加载数据库,我必须以正确的顺序加载它。如果我首先加载 C,那么它会抱怨它无法设置值 C::m_b,因为它应该指向的实例没有加载。

问题是当 A 中还有一个列是其他表之一的外键时,比如说 C。

我可以通过将所有外键加载为字符串来解决问题,然后在加载所有数据后执行查找,但由于有时我必须加载数百万条记录,我无法在这些上花费内存(尽管是临时的) 字符串。

在阅读了关于好的设计(例如“大规模 C++ 软件设计”一书)之后,在我看来,使用循环引用是一个坏主意。例如,如果文件 XH 包含 YH,但 YH 也包含 XH,那么您可能有一个糟糕的设计;如果 X 类依赖于 Y 类,反之亦然,你可能有一个糟糕的设计,应该通过提取这种依赖关系并引入依赖于 X 和 Y 的第三类 Z 来解决这个问题(X 和 Y 将不再相互依赖) .

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

4

4 回答 4

8

从数据建模的角度来看,循环依赖从根本上没有“错误”。这并不意味着模型是错误的。

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

于 2010-10-08T15:06:36.053 回答
4

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

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

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

于 2010-12-02T17:24:47.003 回答
1

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

于 2010-10-08T14:33:58.923 回答
1

唯一需要循环引用的时候是在创建层次结构(例如组织树)时。

Table Employees
   EmployeeID   <----------|
   SupervisorEmployeeID ---|
于 2010-10-08T14:36:08.297 回答