Как обрабатывать необязательные столбцы - PullRequest
1 голос
/ 23 декабря 2010

Database Schema

Мой вопрос связан с ServiceASpecificField и ServiceBSpecificField. Я чувствую, что эти два поля размещены неправильно, потому что для всех записей service A для всех подписчиков в таблице SubscriberServiceMap значение ServiceBSpecificField будет иметь нулевое значение, и наоборот.

Если я перенесу эти два поля в таблицу подписчиков, у меня возникнет другая проблема. Все те абоненты, которые пользуются только service A, будут иметь нулевое значение в Subscribers.ServiceBSpecificField.

Так, что должно быть сделано в идеале?

Ответы [ 4 ]

3 голосов
/ 23 декабря 2010

alt text

поместите проверочное ограничение на Service_A and _B таблицы типа:

alter table Service_A add constraint chk_A check (ServiceID = 1);
alter table Service_B add constraint chk_B check (ServiceID = 2);

тогда вы можете присоединиться как

select *
from SubscriberService as x
left join Service_A    as a on (a.SubscriberID = x.SubscriberID and a.ServiceID = x.ServiceID)
left join Service_B    as b on (b.SubscriberID = x.SubscriberID and b.ServiceID = x.ServiceID)
2 голосов
/ 25 декабря 2010

Это простая проблема подтипа супертипа, которую вы можете решить на 5NF, для этого вам не нужны EAV или улучшенные EAV или 6NF (полный и окончательный правильный EAV).Поскольку значение ServiceAColumn зависит от конкретной подписки подписчика на услугу, то оно должно быть в ассоциативной таблице.

▶ Нормализованная модель данных ◀ (встроенные ссылки не работают в некоторых браузерах / версиях.)

Читатели, не знакомые с реляционнымСтандарт моделирования может найти ▶ Обозначение IDEF1X ◀ полезно.

  • Это обычная структура реляционного супертипа-подтипа.Этот является исключительным: Service является исключительно одним подтипом.

  • Отношения и подтипы более явные и более контролируемые в этой модели, чем в других ответах.Например.Отношения FK относятся только к подтипу Service, а не к супертипу Service.

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

  • Если у вас нет миллионов Services, короткий кодболее подходящий PK, чем бессмысленное число.

Other

  • Вы можете потерять столбец Id в SubscriberService, поскольку он на 100% избыточен и не имеет смысла.

  • PK для SubscriberService равен (SubscriberId, ServiceId), если только вы не хотите дублировать строки.

  • Пожалуйста, измените названия столбцов: Subscriber.Id на SubscriberId;Service.Id до ServiceId.Никогда не используйте Id в качестве имени столбца.Для PK и FK всегда используйте полное имя столбца.Актуальность этого станет ясна вам, когда вы начнете кодировать.

Шестая нормальная форма или EAV

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

Если вы не «хотите» добавлять новые таблицы для каждой новой службы, тогда да, используйте EAV или 6NF, но убедитесь, что у вас есть нормальные элементы управления (безопасность типов) и целостность данных и ссылок, доступные в Relational.базы данных.EAV часто реализуется без надлежащего реляционного контроля и целостности, что приводит ко многим, многим проблемам.Вот вопрос / ответ на эту тему.Если вы согласны с этим, и модели данных в этом вопросе не достаточно объяснительны, дайте мне знать, и я дам вам модель данных, которая соответствует вашим требованиям (DM, который я предоставил выше, является чистым 5NF, потому что этополное требование для вашего исходного вопроса).

2 голосов
/ 23 декабря 2010

Простой способ сделать это - спросить себя: значения этих столбцов различаются в зависимости от Подписка (SubscriberServiceMap таблица) или Сервис ?

Если у каждого подписчика «Услуги А» одинаковое значение для ServiceASpecificField, только тогда вы должны переместить его в таблицу Services.

Сколько таких полей вы ожидаете?ServiceASpecificField, ServiceBSpecificField, C, D ... и так далее?Если число является значительным, вы можете выбрать модель EAV , что потребует создания другой таблицы.

0 голосов
/ 23 декабря 2010

Если значение ServiceSpecificField зависит как от службы, так и от абонента, и для всех пар «абонент-сервис» тип поля одинаков (как я вижу в вашем примере - varchar (50) для обоих полей), тогда я быобновить только таблицу SubscriberSerivceMap:

table SubscriberSerivceMap:
Id
SubscriberId
ServiceId
SpecificField  

Пример такой таблицы:

Id             SubscriberId       Service Id       SpecifiedField
1                 1                   1             sub1_serv1
2                 1                   2             sub1_serv2
3                 2                   1             sub2_serv1
4                 2                   2             sub2_serv2
...