2016-02-15 1 views
1

(У меня немного мозговой пупок, и я не могу вспомнить имя этого проблемного класса, потому что я видел решения для этого раньше на SO, поэтому, пожалуйста, отметьте это как дубликат другого вопроса, если вы найдете здесь лучший ответ).Отношение «один ко многим» с дочерним экземпляром «default»

Представьте, что у нас есть база данных автомобилей и автомобилей. У каждого CarOwner есть много автомобилей (один-ко-многим), но у каждого CarOwner также есть любимый автомобиль.

Вот начальная схема:

CREATE TABLE Owners (
    OwnerId bigint IDENTITY(1,1) PRIMARY KEY, 
    Name nvarchar(100) 
) 

CREATE TABLE Cars (
    CarId bigint IDENTITY(1,1) PRIMARY KEY, 
    Vin  varchar(17), 
    OwnerId bigint, 

    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId) 
) 

для владельца, чтобы любимый автомобиль, Owners таблицы должна быть расширена с помощью нового столбца FaveCarId bigint с внешним ключом к Cars таблице, но добавляет (например, если мы добавили Houses или Computers в базу данных, когда мы получим информацию об Владельце, нам все равно, что их FaveCar. Это также добавляет проблему с курицей и яйцом, где FaveCar столбец должен быть NULL, способный создать Owner, добавьте их новую строку Car, затем добавьте новый CarID обратно в столбец FaveCar.

... так другое решение продлить Cars колонку, чтобы добавить логическое IsFavourite столбец, но это имеет проблема в том, что ничего не мешает кому-то давать два Car с (которые принадлежат к одной и той же Owner) множества IsFavourite колонке стоимость. Уникальное ограничение (между OwnerId+IsFavourite не поможет либо потому, что если владелец имеет 3 или больше автомобилей, 2 из них будет иметь IsFavourite=0.

+0

Я обновил свой ответ, чтобы включить схему наследования базы данных. –

ответ

1

Ассоциация Таблица Решение

CREATE TABLE OwnersFavoriteCar (
    OwnerId bigint PRIMARY KEY, 
    CarId bigint, 
    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId), 
    FOREIGN KEY (CarId) REFERENCES Cars(CarId) 
); 

Вы можете создать таблицу ассоциации , как правило, используется для M:N отношений, но установить первичный ключ OwnerId. Это предотвращает владельца от необходимости более одного любимого автомобиля.

Если вы думаете, что вы можете добавить House или, и что владелец также будет иметь любимца либо в дополнение к Car, вы либо переименовать его в OwnersFavoriteStuff и добавить две колонки:

HouseId bigint -- with FK constraint 
ComputerId bigint -- with FK constraint 

решение наследования Database

Или , вы можете пойти на наследование базы данных:

CREATE TABLE Things (
    ThingId bigint PRIMARY KEY 
    ThingType nvarchar(10) CHECK (ThingType in ('car', 'house')) -- type discriminator 
); 

CREATE TABLE Cars (
    ThingId bigInt PRIMARY KEY, 
    Vin  nvarchar(17), 
    OwnerId bigint, 
    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId), 
    FOREIGN KEY (ThingId) REFERENCES Things(ThingId) 
); 


CREATE TABLE Houses (
    ThingId bigInt PRIMARY KEY, 
    Color nvarchar(17), 
    Rooms bigint, 
    OwnerId bigint, 
    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId), 
    FOREIGN KEY (ThingId) REFERENCES Things(ThingId) 
); 

CREATE TABLE OwnersFavoriteThing (
    OwnerId bigint , 
    ThingId bigint, 
    Type nvarchar(10) CHECK (Type in ('Car', 'House')), -- Used to discriminate amoung different Things 
    PRIMARY KEY (OwnerId, ThingId), -- Makes sure that owner cannot have more than one favorite thing of each type 
    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId), 
    FOREIGN KEY (ThingId) REFERENCES Things(ThingId) 
); 

С этим d atabase, Things - это верхний уровень, а Cars и Houses оба расширения: Things.

Вы обычно используете BEFORE INSERT триггер Cars и Houses, который первым вставить строку в Things, получить новый ThingId и вставить, что в Cars или Houses.

Теперь ваша таблица FavoriteThing остается в третьей нормальной форме, независимо от того, сколько новых таблиц вы создадите в своей базе данных. Столбец type используется для различения различных типов things.

1

Попробуйте следующую модель данных:

enter image description here

IsFavorite является атрибутом OwnedCar и идентифицируются как Люди и автомобиль, а не только от лица или автомобиля. Так что требуется составной ключ.
Вы можете реализовать IsFavorite в качестве столбца OwnedCar или создать новый объект FavoriteCar для добавления целостности.

Чтобы сдержать OwnedCar и FavoriteCar, вам необходимо создать уникальные индексы (альтернативные ключи).

  • Для OwnedCar добавьте уникальный индекс для CarId, чтобы каждый автомобиль мог принадлежать только одному Лицу.
  • Для FavoriteCar добавьте уникальный индекс для OwnerId, чтобы у каждого человека был только один любимый автомобиль.

Проблема без составного ключа является то, что вы можете вставить любимый автомобиль, владелец которого не владеет автомобиля.

CREATE TABLE OwnersFavoriteCar (
    OwnerId bigint PRIMARY KEY, 
    CarId bigint, 
    FOREIGN KEY (OwnerId) REFERENCES Owners(OwnerId), 
    FOREIGN KEY (CarId) REFERENCES Cars(CarId) 
); 
+0

А, хороший момент, я пропустил это. –

Смежные вопросы