Выражение отношения is-a в реляционной базе данных - PullRequest
3 голосов
/ 25 сентября 2008

Мне было интересно, есть ли чистый способ представления отношений is-as, как показано в этом примере:

Эта БД хранит время записи для трех типов программ: фильмы, игровые шоу, драма. В объектно-ориентированном смысле каждый из них - это программа. Каждый из этих подклассов имеет разные свойства. Вот таблицы (префикс fk указывает на внешний ключ):

фильм
ID
Имя
fkDirector

Gameshow
ID
Имя
fkHost
fkContestant

драма
ID
Имя

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

запись
ID
fkProgram
* 1036 начальное время * Конечное время

Единственный способ сделать это без нарушения нормальных форм - это иметь три таблицы записей, а именно recordMovie , recordGameShow и recordDrama .

Есть ли способ объединить эти таблицы в одну, не нарушая принципов нормализации базы данных?

Вот несколько нерабочих примеров, иллюстрирующих идею:

Программа
ID
fkMovie
fkGameShow
fkDrama

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

Программа
ID
fkSpecific ← fkMovie ИЛИ fkGameShow ИЛИ fkDrama
fkType ← будет указывать, в какую таблицу смотреть

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

Я просто пытаюсь сэкономить, имея здесь 3 таблицы вместо одной. Может быть, это просто не относится к RDB.

Ответы [ 6 ]

2 голосов
/ 08 февраля 2009

Выполните поиск в Google по «Обобщение специализации реляционного моделирования».

Модель "gen-spec" следует той же схеме, что и отношения "is-a".

Например, автомобиль - это специализированный автомобиль. Грузовик - это другое специализированное транспортное средство. Мотоцикл - третий вид специализированного транспортного средства.

Тебе нужно найти много статей.

Интересно, что если вы просто выполните поиск в Google по "gen-spec", то одна из главных ссылок - это описание моделирования gen-spec в Smalltalk.

2 голосов
/ 25 сентября 2008

Почему вы хотите хранить все данные в одной таблице? Это явно разные сущности. Ваша идея главной таблицы Record , со вспомогательной recordMovie , recordGameShow и RecordDrama .

Чтобы наладить связь "is-a" между вспомогательными таблицами и главной, вам нужно объявить Record.id как внешний ключ во всех этих таблицах, а также добавить к нему ограничение, чтобы оно было уникальным - это навязывает взаимно-однозначное отношение, которое преобразует эти таблицы в расширения основной.

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

2 голосов
/ 25 сентября 2008

Да, это должна быть одна таблица, как

Programs:
   id,
   name,
   type_id,
   length,
   etc...

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

ProgramType
   type_id,
   type_name,
   etc...

Вот так.

1 голос
/ 25 сентября 2008

Это довольно стандартная проблема, с которой сталкивались многие люди раньше, и все подходы, которые вы можете рассмотреть, возможно, были выполнены в какой-то момент.

A Простой поиск в Google предлагает довольно хорошие объяснения плюсов и минусов каждого из них.

0 голосов
/ 25 сентября 2008

Это хорошие статьи на эту тему:
http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/
http://www.agiledata.org/essays/mappingObjects.html

Это то, что я в конечном итоге сделаю. Моя таблица программ будет просто:

Программа
ID

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

фильм
ID
fkProgram
Имя
fkDirector

запись
ID
fkProgram
* 1031 начальное время * Конечное время

0 голосов
/ 25 сентября 2008

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

Могут быть добавлены другие столбцы, такие как fkDirector, fkMovie. Затем добавьте ограничение, что когда ProgramType является фильмом, fkDirector не может быть нулевым или когда это шоу, fkHost не может быть нулевым.

Это позволяет легко просматривать все фильмы / шоу / ..., записанные между началом и окончанием. Также убедитесь, что все данные заполнены и ссылки верны.

У кого-нибудь есть идея получше?

...