Сложные связи с базой данных (таблицы соединений) - PullRequest
1 голос
/ 29 сентября 2011

Мой вопрос о идее объединения двух соединительных таблиц в одну для похожих таблиц. Пожалуйста, прочитайте, чтобы понять, что я имею в виду. Также обратите внимание, что это действительно проблема, с которой я столкнулся, и поэтому имеет отношение к этому форуму. Это просто тема с широкими последствиями, для которой я надеюсь привлечь немного больше участия различных специалистов, чтобы получить лучшую перепись «наилучшей практики», если хотите.

У меня довольно сложная проблема проектирования баз данных. Я надеюсь, что это будет своего рода вики, в которую многие люди могут внести свой вклад и извлечь уроки. Чтобы упростить это, я создал набор графики и разделю проблему на 1) процесс и 2) структуру.

Шаги процесса

  1. Сделан запрос (DocRequest) на документацию (Публикация).
  2. Новая публикация создается, ЕСЛИ указанная публикация еще не существует.
  3. Текущий журнал (StatusReport) сохраняется для прогресса в выполнении запроса.

Примечание. Для любой данной публикации может быть много DocRequests и StatusReports (включая обновления)

Структура базы данных

Примечание. Таблицы DocRequest и StatusReport имеют множество полей и вспомогательных таблиц, которые не показаны на прилагаемой графике. Кроме того, конкретная публикация является основной записью, которой принадлежат все записи в этих таблицах.

- Текущая реализация-- enter image description here

Примечание. Основным недостатком этого дизайна является то, что всякий раз, когда вы создаете новую запись DocRequest и StatusReport, вы также должны создавать новую запись в таблице Publications (которая действует как таблица соединений), но это также создает новую публикацию в результате. Это не желаемое поведение.

- Типичная реализация-- (для этого типа отношений) enter image description here

Примечание. Это нормально и, вероятно, идеально, но обрабатывает обновления таблиц DocRequest и StatusReport, независимо связывая их с публикацией, к которой они принадлежат.

- Моя предпочтительная реализация-- (для этого особого случая) enter image description here

Примечание. Идея, которую я здесь привел, состояла в том, чтобы просто объединить двойные соединительные таблицы в одну. В этом случае соединительная таблица получит новую запись в любое время, когда в DocRequest или StatusReport произойдет вставка. Я, вероятно, справлюсь с этим с помощью триггера.

Обсуждение

Теперь для обсуждения. Я хотел бы узнать от моих коллег-разработчиков баз данных, считаете ли вы, что это плохая идея, и какие проблемы могут возникнуть из-за этого. Я думаю, что чистое количество записей должно быть таким же, как и в двух отдельных таблицах соединений, и фактически использует немного меньше места, сохраняя дополнительный столбец ID. :)

Дайте мне знать, что вы, ребята, думаете. Я бы очень хотел, чтобы в эту дискуссию было вовлечено много людей. Ура! :)

1 Ответ

2 голосов
/ 29 сентября 2011

Я думаю, что вы наносите себе вред, думая с точки зрения соединительных таблиц. Просто подумай о столах.

  • Поскольку StatusReport связан со статусом запроса документа, вам нужна таблица, которая как-то связана с этими двумя .
  • «StatusReport» - ужасное имя для таблицы, в которой хранятся факты о состоянии запроса документа.
  • «ID» - ужасное имя для любого столбца в любой таблице.
  • Идентификационный номер публикации, похоже, больше связан с запросом документа, чем со статусом запроса. (Вы сказали: «Новая публикация создается, ЕСЛИ указанная публикация еще не существует». Честно говоря, это катание довольно близко к краю бессмысленности.) Таким образом, номер публикации почти наверняка принадлежит таблице DocRequest.

Обращаясь к диаграмме вашей предпочтительной реализации, я бы отбросил таблицу TripleJunction и заменил бы StatusReport этим.

-- Predicate: Document request number (doc_request_id) has status (status) 
--            as of date and time (status_as_of).
create table document_request_status (
  doc_request_id integer not null references DocRequest (id),
  status_as_of timestamp not null default current_timestamp,
  status varchar(10) not null,
  -- other columns go here
  primary key (doc_request_id, status_as_of)
);
...