2014-11-25 2 views
0

Пожалуйста, проверьте таблицу ниже для упрощенной версии моей проблемы:Поля ссылки две таблицы - внешний ключ Конфликт

Таблица мальчики

BoyId 
BoyName 
... 

Таблица Девушка

GirlId 
GirlName 

Настольные игрушки

ToyId 
ToyName 
ToyOwnerBoyOrGirl (The toy could be owned by a boy or a girl) 
ToyOwnerId 

Я создал два ограничения:

1) ToyOwnerId является внешним ключом первичного ключа Boys.BoyId

2) ToyOwnerId является внешним ключом первичного ключа Girls.GirlId

Моя цель заключается в том, чтобы сообщить базе данных, что ToyOwnerId всегда будет одним из этих идентификаторов

Моя проблема: Когда я попытался вставить новую Игрушку с идентификатором Мальчика, у меня появилась ошибка, в которой есть ограничение foreign key conflict.

Это дизайн сумки или я все еще могу использовать ту же конструкцию с исправлением?

+0

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

+0

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

ответ

1

Похоже на плохой дизайн. Почему у меня нет одного стола для всех детей и какой-то знак - это мальчик или девочка? Также я действительно сомневаюсь, что вам нужно поле ToyOwnerBoyOrGirl - так как его можно легко получить, присоединившись к игрушкам владельцам.

Рассмотрим следующую схему:

Table Children 
ID 
Name 
Is_Boy 

Table Toys 
ID 
Name 
Owner_ID 

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

EDIT: Согласно комментарию OP - таблицы для мальчиков и девочек совершенно разные.

Итак, в этом случае у вас все еще может быть таблица Children (давайте использовать предыдущую терминологию) в качестве «общей» таблицы для Boys и Girls.

Что-то вроде:

Table Children 

ID 
Table_Name ('Boys' or 'Girls' here) 
Record_ID (ID from Boys or Girls respectively) 
...maybe some common fields from boys and girls tables here... 


Table Boys 
ID 
Child_ID 
...the rest of fields 

Table Girls 
ID 
Child_ID 
...the rest of fields 
+0

Да, но каждая таблица имеет совершенно другой набор полей, одна имеет до 80 полей, а другая имеет только 10 полей. Обратите внимание, что таблицы Boy and Girls являются просто синонимами моих фактических имен таблиц, которые более сложны – user3340627

+0

См. Обновленный ответ –

2

Я думаю, вы должны объединить таблицу мальчиков и девочек в одной таблице называемых детей. У него будет половая колонка, у которой будет M или F. Это упростит ситуацию.

+0

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

+1

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

2

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

Таблица Игрушки

  • ToyId
  • ToyName
  • ToyOwnerBoyId
  • ToyOwnerGirlId
 
    CONSTRAINT chkToyOwner CHECK 
    (
    (ToyOwnerBoyId is null and ToyOwnerGirlId is not null) 
    OR 
    (ToyOwnerBoyId is not null and ToyOwnerGirlId is null) 
) 

Как выбрать данные, использовать внешние соединения:

select ... 
from toys 
left join boys on boys.boyid = toys.toyownerboyid 
left join girls on girls.girlid = toys.toyownergirlid; 

Чтобы найти игрушки, принадлежащие мальчиков:

select ... 
from toys 
where toyownerboyid is not null; 
+0

Звучит прекрасно. – user3340627

0

Это плохой дизайн, учитывая тот факт, один набор столбцов (один столбец, будучи ToyOwnerId) упоминается различных таблиц, так как одно- столбец FK в одностолбцовую PK. Тогда был бы очевидный вопрос: как получилось, что у вас разные таблицы с аналогичным PK? И я вижу, вы уже ответили, что, отвечая на столбцы данных соответствующих таблиц, разные. Это хорошая причина иметь разные таблицы. Но тогда, как решить проблему FK? (Я понял, что эти «мальчики» и «девочки» не являются реальными сущностями). Что вы можете сделать, это сделать BoyToy и таблицу GirlToy. Если у вас очень мало столбцов данных (data = non-PK и non-FK), то это идеальное решение. Нет?

+0

Спасибо за ваш ответ. Это будет хорошим решением, если бы это была таблица игрушек, но у меня было 2 или 3 игрушечных стола, и это означает, что мне придется удвоить их все – user3340627

+1

OK. Ну, тогда это зависит от того, как эти «игрушечные» вещи связаны друг с другом. Вам нужно будет увидеть влияние на каждое изменение: различия в структурных таблицах приводят к очень различным командам INSERT/UPDATE/DELETE, и вы также должны учитывать их легкость. Простая установка таблицы иногда может привести к кошмарам кодирования. Не говоря уже: если вы можете избежать триггеров и полагаться на PK/FK, последнее - на мой взгляд - лучшее решение. – tvCa

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