外键中的循环依赖:使用它还是避免使用它?

Pat*_*ick 7 database-design foreign-keys application-design application-dependency

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

  • 表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类,反之亦然,那么你可能有一个糟糕的设计,应该通过提取这个依赖并引入第三个Z来解决,它取决于X和Y(X和Y将不再依赖于彼此) .

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

nvo*_*gel 5

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

遗憾的是,大多数SQL DBMS无法有效实现此类约束,因为它们不支持多个表更新.通常,唯一的方法是临时暂停一个或多个约束(例如使用"可延迟"外键或类似功能)或通过更改模型以使约束的某些部分可选(将其中一个引用列放入新表).这只是一个令人讨厌的SQL限制的解决方法,但是,这并不意味着你做错了.


Rob*_*vey 1

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

Table Employees
   EmployeeID   <----------|
   SupervisorEmployeeID ---|
Run Code Online (Sandbox Code Playgroud)

  • 你很绝对。我还能想到很多案例。例如,“1:N”关系怎么样,您需要指向“N 集”中最后添加的行?或者下面“阿德里安·史密斯”提到的。当然,您可以解决它的需要,但您也可以在您的示例中这样做。 (2认同)