Вариант № 1 гарантирует, что каждая страница принадлежит одному и только одному другому объекту, хотя на самом деле связь не может быть установлена, поскольку поле parentId может указывать более чем на одно место.
Верно. С точки зрения реляционной теории проблема заключается в том, что ваш столбец "parentId
" нарушает третью нормальную форму, потому что его значение зависит от строки в зависимости от значения в parentType
(не ключевой столбец).
У вас не будет правильно спроектированной базы данных, если один столбец может содержать чей-то номер телефона или его дату рождения в каждой строке, в зависимости от какого-либо другого флага. Это два разных факта о человеке, и каждый из них заслуживает отдельной колонки. Точно так же сохранение site_id или node_id в одном столбце будет иметь ту же проблему.
Еще один признак того, что это ошибочный дизайн, заключается в том, что вы не можете объявить ограничение внешнего ключа так, чтобы оно указывало на любую из двух таблиц, на которые ссылаются.
Вариант № 2 чище, но в основном он говорит, что сайт «принадлежит» двум страницам с ошибками и не найденным, и это, вероятно, плохая практика.
Я понимаю, почему вы так говорите, потому что принадлежит соглашениям в Rails-подобных фреймворках. Но это условности; они не обязательно являются единственными отношениями, которые могут моделировать внешние ключи. Вы можете сделать так, чтобы один объект ссылался ровно на один другой объект в отношении has one. В этом случае внешний ключ меняет направление.
Я бы сказал, что логически верно, что страница с ошибкой и страница «Не найдено» принадлежат сайту, а не наоборот. И способ сделать их обязательными состоит в том, чтобы другой объект ссылался на эти страницы и применял ограничение NOT NULL
к этим ссылкам. Это то, что вы описали.
CREATE TABLE site (
. . .
error_page_id INT NOT NULL,
notfound_page_id INT NOT NULL,
FOREIGN KEY (error_page_id) REFERENCES pages (page_id),
FOREIGN KEY (notfound_page_id) REFERENCES pages (page_id)
);
Это отвечает вашим неотложным потребностям, это применимо и находится в нормальной форме.
@NXC предлагает создавать фиктивные узлы для страниц ошибок и не найдено. Хотя это позволяет хранить эти узлы в иерархии узлов, это не обеспечивает обязательного наличия этих страниц на сайте. То есть сайт может храниться без ссылок на эти узлы.
@Tony Andrews предлагает сохранять два столбца на каждой странице, site_id
и site_node_id
и добавление ограничения CHECK, чтобы гарантировать, что ровно одно из них не равно NULL. Это кажется лучше, чем вариант parent_id
/parent_type
, но он по-прежнему не обеспечивает какого-либо принудительного выполнения того, что на каждом сайте должны быть страницы с ошибками и страницами «Не найдено».
person
Bill Karwin
schedule
11.02.2009