Круговые зависимости во внешних ключах: использовать это или избегать? - PullRequest
7 голосов
/ 08 октября 2010

Мое приложение загружает много данных из базы данных в сложную структуру данных. Структура данных в памяти повторяет структуру базы данных, что означает, что если база данных содержит следующие таблицы:

  • таблица А, ключ А1
  • таблица 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 ++»), мне кажется, что вообще плохие идеи иметь круговые ссылки. Например. если файл X.H содержит Y.H, но Y.H также содержит X.H, возможно, у вас плохой дизайн; если класс X зависит от класса Y, и наоборот, у вас, вероятно, плохой дизайн, который должен быть решен путем извлечения этой зависимости и введения третьего класса Z, который зависит от X и Y (X и Y больше не будут зависеть друг от друга) .

Является ли хорошей идеей также распространить это правило на дизайн базы данных? Другими словами: предотвращение циклических ссылок во внешних ключах.

Ответы [ 4 ]

5 голосов
/ 08 октября 2010

С точки зрения моделирования данных нет ничего в корне «неправильного» с круговой зависимостью.Это не означает, что модель неверна.

К сожалению, большинство СУБД SQL не могут эффективно реализовать такие ограничения, поскольку они не поддерживают обновления нескольких таблиц.Обычно единственный способ обойти это - временно приостановить одно или несколько ограничений (например, используя «отложенный» внешний ключ или аналогичные функции) или изменить модель, чтобы сделать некоторую часть ограничения необязательной (поместить один из столбцов, на которые ссылаются, вновый стол).Однако это всего лишь обходной путь для неприятного ограничения SQL, но это не значит, что с самого начала вы сделали что-то не так.

4 голосов
/ 02 декабря 2010

Вы должны смоделировать данные, которые у вас есть.Если в данных есть круговая связь (например, каждая фотография принадлежит папке, но у каждой папки есть одна фотография обложки), то правильно смоделировать это как круговую связь в базе данных.

У меня была только такая ситуацияодин раз при использовании Oracle, поэтому у меня не было возможности проверить, как реализовать такие отношения в других базах данных.Но для Oracle вы можете прочитать мою статью здесь:

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

2 голосов
/ 08 октября 2010

Единственный раз, когда вам понадобится циклическая ссылка, - это когда вы создаете иерархическую структуру, например организационное дерево.

Table Employees
   EmployeeID   <----------|
   SupervisorEmployeeID ---|
1 голос
/ 08 октября 2010

Да, циклические зависимости в базах данных являются хорошим поводом для переосмысления проекта.

...