Дилемма схемы базы данных с внешними ключами, указывающими на несколько таблиц (исключительная дуга) - PullRequest
1 голос
/ 18 августа 2010

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

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

авиакомпания (id, имя, ...)
отель (id, name, ...)
поставщик (идентификатор, имя, ...)
событие (идентификатор, имя, ...)
eventComponent (id, name) {например, питание, прокат номеров, аудио / видео ...}
eventFlight (id, Eventid, Airlinesid, ...)
eventHotel (id, eventid, hotelid, ...)
eventSupplier (id, eventid, supplierid, hotelid, eventcomponentid, ...)

Таким образом, авиакомпания, гостиница, поставщик - это все справочные таблицы, и создается событие с отношением 1 ко многим между этими справочными таблицами. Например, событие может иметь 2 записи о рейсе, 3 записи о других компонентах и ​​2 записи об отеле. Но проблема в том, что в таблице EventSupplier поставщиком может быть либо Поставщик, либо существующая Гостиница. Поэтому после того, как пользователь построил свое новое событие на внешнем интерфейсе, мне нужно сохранить его таким образом, чтобы не было кошмаром возвращать эти данные позже.

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

Я думал:

CREATE TABLE eventSupplier (
id SERIAL PRIMARY KEY,
Eventid INT NOT NULL,
hotelid INT,
поставщик INT,
УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ (Eventid, Hotelid, Supplierid), - УНИКАЛЬНЫЕ разрешения NULLs
ПРОВЕРКА ОГРАНИЧЕНИЯ (hotelid НЕДЕЙСТВИТЕЛЕН ИЛИ Supplierid НЕ НУЛ),
ИНОСТРАННЫЙ КЛЮЧ (hotelid) ССЫЛКИ hotel (id),
ИНОСТРАННЫЙ КЛЮЧ (supplierid) ССЫЛКИ поставщик (id)
);

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

выберите e.id в качестве Eventid, объедините (h.name, s.name) в качестве поставщика
от eventSupplier es
левое внешнее соединение
поставщики на s.id = es.supplierid
левое внешнее соединение
отель h on h.id = es.hotelid
где h.id не ноль ИЛИ s.id не нуль

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

Любые мысли по этому поводу будут высоко оценены!

Приветствие Фил

Ответы [ 2 ]

1 голос
/ 18 августа 2010

Как насчет обработки событий по одному и использования EventGroup для их группировки? alt text

EDIT

Я просто переименовал сущности, чтобы соответствовать последним комментариям. Это как можно ближе к этому - по общему признанию, я не понимаю проблему должным образом.

alt text

0 голосов
/ 06 сентября 2010

Хороший способ проверить ваше решение - подумать о том, что произойдет, если авиакомпания станет поставщиком. Ваше решение справляется с этим или начинает усложняться.

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

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

...