Таблица соединений и вопрос нормализации

Мне трудно понять, приемлем ли следующий шаблон проектирования. У меня есть следующие требования (и некоторые другие) для реляционной модели:

1) Он должен иметь возможность представлять приложения (такие как AppA, AppB, AppC), каждое со своим собственным набором атрибутов.

2) Каждое приложение может обмениваться данными через различные каналы, такие как Internet (электронная почта, Twitter, Facebook), Phone (SMS, MMS и т. д.), так что между программами и каналами существует отношение "многие ко многим".

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

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

По сути, я создал четыре таблицы, Program, Channel, Ident и CommunicationType, для хранения информации о каждой из них, и вместо создания соединительных таблиц для (Program, Channel), (Program, Identifier) и т. д., что только усложнило бы дизайн, я создал единая таблица, состоящая из первичных ключей этих четырех таблиц с уникальным ограничением на (Program, Channel, Ident, CommunicationType). Теперь каждая запись этой таблицы связана с данным сообщением.

Конечно, это решает мою проблему довольно простым способом, но теперь я задаюсь вопросом, приемлемо ли это вообще, если это противоречит принципам нормализации. Кто-нибудь может дать мне мнение?


person User    schedule 02.07.2011    source источник


Ответы (3)


По сути, я создал четыре таблицы: Program, Channel, Ident и CommunicationType для хранения информации о каждой из них и,

Это хорошая идея.

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

Вы должны быть осторожны с одной вещью, когда вы проектируете такие таблицы. Ваша структура, имеющая ключ {Program, Channel, Ident, CommunicationType}, допускает все возможные комбинации Program и Channel, Channel и Ident, Program и CommunicationType и так далее. Иногда это плохая идея.

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

И именно поэтому это плохая идея. Кажется, вы говорите, что не каждая комбинация Ident, Program и CommunicationsType допустима.

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

Создайте таблицу с ключом {Program, Ident, CommunicationsType}. Таблица с ключом {Program, Channel, Ident, CommunicationType} может установить на нее ссылку внешнего ключа.

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

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

create table pc (
    program_name varchar(10) not null references programs (program_name),
    channel_name varchar(10) not null references channels (channel_name),
    primary key (program_name, channel_name)
);

create table pict (
    program_name varchar(10) not null,
    channel_name varchar(10) not null,
    comm_type varchar(10) not null references communication_type (comm_type),
    primary key (program_name, channel_name, comm_type),
    foreign key (program_name, channel_name) 
        references pc (program_name, channel_name) 
);

create table your-table-name (
    program_name varchar(10) not null,
    channel_name varchar(10) not null,
    comm_type varchar(10) not null,
    ident varchar(10) not null,
    primary key (program_name, channel_name, comm_type, ident),
    foreign key (program_name, channel_name, comm_type) 
        references pict (program_name, channel_name, comm_type),
    foreign key (ident) references ident (ident)
);

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

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

person Mike Sherrill 'Cat Recall'    schedule 03.07.2011
comment
+1. Большое спасибо за ваш ответ! Я думаю, что я собираюсь следовать этому дизайну. Вы правы, я имел в виду, что не каждая комбинация {Program, Ident, CommunicationType допустима. И мне также нужна таблица с ключом {Канал, Программа}, поэтому я еще раз благодарю вас за ваш дизайн. - person User; 03.07.2011

я бы не стал этого делать.

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

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

person Randy    schedule 03.07.2011
comment
+1. Вы правы, теперь я вижу, что это не очень хорошая идея. Большое спасибо. - person User; 03.07.2011

Извините за предоставление вам ответа, который запрашивает дополнительную информацию. Моя репутация на данный момент не позволяет комментировать...

Я не вижу ничего плохого в выбранном дизайне, основываясь на объяснении.

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

Ведь он бы работал и без единой таблицы со всеми ключами и составным уникальным индексом. Блокировка всех комбинаций таким образом является довольно ограничительной.

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

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

person HighCs    schedule 02.07.2011
comment
+1. Большое спасибо за ваш ответ! Моя цель — нигде не хранить избыточную информацию, поэтому я очень полагаюсь на соединения между таблицами. - person User; 03.07.2011