Составной вопрос внешнего ключа - PullRequest
1 голос
/ 02 апреля 2009

Я пытаюсь выяснить, можно ли таким способом создать внешний ключ.

Сначала в этом сценарии есть две родительские таблицы.

В таблице 1 есть PK int и другой столбец int. Когда они объединены, они уникальны.

В таблице 2 есть PK int и еще один столбец int. Когда они объединены, они уникальны.

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

Таблица 3 содержит значение для PK и другого столбца int из одной из первых двух таблиц. Он надежно выбирается, поскольку оба поля, используемые в поиске, являются уникальными для одной из таблиц выше.

Так что я хочу создать ФК или, возможно, два ФК для этого сценария. Я хотел бы иметь возможность делать каскадное удаление из любой из первых таблиц в третью таблицу, а также хотел бы использовать это для отношений сущностей в Entity Framework.

Пожалуйста, дайте мне знать, если это не имеет смысла. Я прочитал это несколько раз, и это настолько ясно, насколько я могу понять.

Спасибо

Ответы [ 3 ]

1 голос
/ 02 апреля 2009

Если я вас правильно понимаю, у вас есть 3 таблицы, структурированные следующим образом:

TABLE_A:
    PK_FIELD int NOT NULL
    OTHER_FIELD int NOT NULL, NOT IN TABLE_B.OTHER_FIELD

TABLE_B:
    PK_FIELD int NOT NULL
    OTHER_FIELD int NOT NULL, NOT IN TABLE_A.OTHER_FIELD

TABLE_C:
    PK_FIELD int NOT NULL
    OTHER_FIELD int NOT NULL IN (TABLE_A.OTHER_FIELD OR TABLE_B.OTHER_FIELD

То, что вы пытаетесь сделать, это определить TABLE_C так, чтобы вы могли каскадно обновлять и удалять между таблицами. Из-за того, как определены TABLE_A.OTHER_FIELD и TABLE_B.OTHER_FIELD, вы гарантируете, что между ними нет перекрытия. Проблема в том, чтобы выяснить, какая таблица имеет ссылку на TABLE_C.

То, что вы можете сделать с этим определением, - это каскад с TABLE_A или TABLE_B до TABLE_C, так как в этом направлении связь достаточно ясна. Однако каскадировать от TABLE_C вверх сложнее, так как вы не знаете, к какой таблице каскадироваться. Либо определите два поля в TABLE_C по одному, чтобы ссылаться на каждую из других таблиц, и затем вы можете определить отношения между всеми тремя таблицами, зная, что для любой данной записи будет задействована только одна или две таблицы, но не все три. В качестве альтернативы, вы можете использовать код, чтобы выяснить, к какой таблице нужно связать эту конкретную строку и каскадировать ее соответственно.

0 голосов
/ 02 апреля 2009

Если в Table3 содержатся все значения в Table1 UNION Table2, то у вас есть схема наследования :

Table3 { (int id, int type) PK }
Table1 { (int id, int type [CHECK type = 1]) FK Table3 }
Table2 { (int id, int type [CHECK type = 2]) FK Table3 }

При этом удаление из Таблицы3 будет каскадно перемещаться в Таблицу 1 или Таблицу 2.

В противном случае, если Table3 - это только подмножество Table1 UNION Table2 - тогда будет работать Table4 как полный набор.

Table4 { (int id, int type [CHECK type IN (1,2)]) PK }
Table1 { (int id, int type [CHECK type = 1]) FK Table4 }
Table2 { (int id, int type [CHECK type = 2]) FK Table4 }
Table3 { (int id, int type) FK Table4 }

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

Изменить (потому что я думаю, что это важный момент, который следует видеть отдельно от комментариев):

Да, проблема в том, что один и два являются родителями. Они оба имеют связанные записи в 3, которые будут FK, а не PK для этой таблицы. Кажется, что это практически невозможно при использовании ограничения FK. Спасибо за ответ! - Крис (час назад)

IMO - ваша модель данных нарушена. Table1 и Table2 не связаны, но вы пытаетесь вставить их в один столбец в Table3. Если Таблица1 и Таблица2 как-то связаны, то вам нужно смоделировать это.

Либо введите родительскую таблицу (Table4), если они связаны, либо 2-й столбец в Table3 (Table1 FK, Table2 FK) или 2 таблицы объединения, если они не связаны. Не пытайтесь вставить круглый колышек в квадратное отверстие - и не пытайтесь восполнить это с помощью спускового крючка. ;)

0 голосов
/ 02 апреля 2009

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

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