2009-04-02 2 views
1

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

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

Таблица 1 имеет PK int и другую колонку int. При объединении они уникальны.

Таблица 2 имеет PK int и другую колонку int. При объединении они уникальны.

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

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

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

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

Благодаря

ответ

0

Если Таблица3 содержит все значения в Table1 UNION Table2, то у вас есть inheritance scheme:

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 } 

С, что, удаляя из Table3 будет каскадные Table1 или Table2 соответствующим образом.

В противном случае, если Table3 является только поднабором таблицы 1 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 } 

Для обработки каскадных удалений, хотя, вам нужно удалить из table4 (хотя вы могли бы сделать триггер Table3, чтобы справиться с этим для вас).

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

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

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

Либо введите родительскую таблицу (Таблица 4), если они связаны, либо либо второй столбец в Таблице 3 (Таблица 1 FK, Таблица2 FK), либо 2 таблицы объединений, если они не являются. Не пытайтесь вставить круглую привязку в квадратное отверстие - и не пытайтесь наверстать это с помощью триггера. ;)

+0

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

+0

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

+0

Я полностью согласен, но у меня нет контроля над этим. Спасибо за комментарии, они проверяют, что я думаю полностью. – Chrisb

1

Если я вас правильно понимаю, вы 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

Да, это точно. Я не забочусь о том, чтобы вернуться из таблицы 3. Вы случайно не знаете, какой код T-SQL мне понадобится для создания ограничений в таблице 3? – Chrisb

+0

Я не уверен, есть ли способ определить формальное ограничение, которое даст вам это с помощью одного столбца. Если вы используете решение с двумя столбцами, то каждое поле имеет значение NULL, и существует ограничение таблицы, в котором ровно одно из двух полей равно null. – Elie

0

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

+0

Я использую SQL Server 2005. – Chrisb

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