Модель БД для многих таблиц с отношением ноль-ко-многим к одной и той же таблице - PullRequest
0 голосов
/ 06 июля 2011

Я создаю схему БД для PostgreSQL 9.0 БД, которая будет представлять множество реальных сущностей, с таблицей на сущность.Большинство из этих объектов могут иметь 0 или более текстовых заметок, связанных с ними.Однако «примечание» также имеет некоторые атрибуты, поэтому оно должно быть собственной таблицей - я не могу просто использовать массив строк.Итак, логически:

EntityA -> 0..* Note
EntityB -> 0..* Note
EntityC -> 0..* Note

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

До сих пор я придумал 3 варианта:

  1. Столбец для идентификатора каждого типа объекта в таблице примечаний с внешним ключом.Это очень уродливо, потому что есть много сущностей.

  2. Соединяющая таблица для каждой таблицы сущностей, соединяющая ее с Note.Это по-прежнему некрасиво, поскольку удваивает количество таблиц и может также повлиять на производительность (дополнительное объединение).

  3. Общий столбец «entityId» в таблице «Примечание», который логически ссылается на любой изтаблицы, но не применяется с внешним ключом.Я также могу использовать одну и ту же последовательность PostgreSQL для всех идентификаторов сущностей, чтобы автоматически сгенерированный идентификатор был уникальным для всех сущностей, а не только для сущностей этого типа.Однако это не защищает от ошибок, потому что кто-то может вставить идентификатор вручную.

Пока я склоняюсь к третьему варианту.Он сохраняет схему в чистоте, но нет ссылочной целостности, что не идеально.Кто-нибудь может предложить лучший подход?

Ответы [ 4 ]

2 голосов
/ 06 июля 2011

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

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

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

1 голос
/ 06 июля 2011

При условии, что:

  • "Многие" - это управляемое количество объектов (решать вам)
  • Есть несколько общих столбцов среди объектов (например, EntityName)
  • Одна нота принадлежит только одной сущности, у одной сущности может быть много заметок.

Вы можете попробовать что-то вроде

enter image description here

EDIT

В следующем сценарии таблица Entity имеет только EntityID и EntityType, в то время как каждая таблица E_Type_X имеет все столбцы.Единственная цель таблицы Entity - генерировать уникальные ключи, которые затем распространяются на каждую таблицу E_Type_X.Из-за распространения ключа каждая таблица E_Type_X может быть непосредственно присоединена к таблице Notes.

Это логический эквивалент всех таблиц E_Type_X, использующих одну и ту же последовательность для генерации ключа - такблизко к вашему решению № 3, но все ограничения внешнего ключа могут быть реализованы.

1 голос
/ 06 июля 2011

Я бы выбрал вариант 2, так как это более нормализованная структура, и я не стал бы беспокоиться о присоединении.

Если вы беспокоитесь о том, чтобы выглядеть «уродливо», просто создайте вид.

0 голосов
/ 21 июля 2011

В итоге я решил не создавать никаких новых таблиц для этого и вместо этого создал несколько правил. Однако я принимаю ответ Дамира Судревича , потому что он наиболее близок к тому, что я хотел (и мне нравится тот факт, что он нарисовал для меня диаграмму!)

По сути, я хотел решить две проблемы:

  1. Убедитесь, что при удалении сущности все ее Примечания.
  2. Убедитесь, что примечание не может быть создано без ссылки на действительный объект.

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

CREATE OR REPLACE RULE rl_somentity_delete_note
AS ON DELETE TO someentity
DO ALSO DELETE FROM note WHERE entity_id = OLD.id

Вторая проблема не была решена. Я решил, что лучше взять на себя (низкий) риск того, что пользователи будут создавать «осиротевшие» заметки, чем усложнять схему дополнительной таблицей и дополнительным FK для каждой таблицы сущностей, что потребует дополнительного оператора INSERT для добавления каждой строки сущности .

...