Круговые зависимости во внешних ключах: использовать это или избежать?

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

  • таблица А, ключ А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.

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

Прочитав о хорошем дизайне (например, книгу "Разработка больших программ на С ++"), мне кажется, что вообще плохая идея - иметь круговые ссылки. Например, если файл XH включает YH, но YH также включает XH, вероятно, у вас плохой дизайн; если класс X зависит от класса Y, и наоборот, у вас, вероятно, плохой дизайн, который должен быть решен путем извлечения этой зависимости и введения третьего класса Z, который зависит от X и Y (X и Y больше не будут зависеть друг от друга),

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

4 ответа

Решение

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

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

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

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

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

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

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

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

Другие вопросы по тегам