2009-07-27 3 views
21

Я определяю базу данных для системы клиент/заказ, где есть два очень разных типа клиентов. Потому что они настолько разные, что одна таблица клиентов была бы очень уродливой (она была бы заполнена нулевыми столбцами, поскольку они бессмысленны для одного типа).Несколько внешних ключей для одного столбца

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

Кроме того, я планирую использовать nHibernate как ORM, могут возникнуть проблемы, возникающие при выполнении таких отношений?

ответ

19

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

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

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

+1

Согласовано. Нормализация - это ключ здесь. – jva

+1

@Guffa: -1, потому что «Нет, у вас не может быть отдельного поля в качестве внешнего ключа для двух разных таблиц» - это утверждение неверно (по крайней мере, на SQL Server 2005). Дайте ему вихрь. – Liao

+2

@ Liao: Я не думаю, что вы понимаете ситуацию ... Если вы, например, имеете значение внешнего ключа 42, как бы вы узнали, является ли это ключом в таблице A или таблице B? – Guffa

3

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

CustomerA <---- CustomerA_Orders ----> Order 
CustomerB <---- CustomerB_Orders ----> Order 

Так приказ не даже имеют иностранный ключ; желательно ли это, хотя ...

1

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

Лучше всего будет иметь таблицу CustomerType с возможными столбцами - CustomerTypeID, CustomerID, где CustomerID является PK, а затем направлять вашу таблицу OrderID в CustomerID.

Радж

0

Два различных типа клиента является классическим примером типов и подтипов, или, если вы предпочитаете, классы и подклассы. Here - ответ от другого вопроса.

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

0

Как уже отмечалось, если ключ, скажем, 12345, как бы вы узнали, в какой таблице его искать? Вы могли бы, я полагаю, сделать что-то, чтобы гарантировать, что ключевые значения для двух таблиц никогда не перекрываются, но это слишком уродливо и мучительно созерцать. У вас может быть второе поле, в котором указывается тип клиента. Но если у вас будет два поля, почему бы не указать одно поле для идентификатора клиента 1 и другое для идентификатора клиента 2.

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

1

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

Он использовал столбец GUID (тип «uniqueidentifier»), чтобы избежать проблемы двусмысленности, и он отключил проверку ограничений внешних ключей, так как гарантировано, что только один будет соответствовать. Но я могу придумать множество причин, которых вы не должны, и я не думал о каких-либо причинах, которые вам следует.

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

0
  1. Создайте таблицу «клиент», которая включает все столбцы, которые имеют одинаковые данные для обоих типов клиентов.
  2. чем создать таблицу "customer_a" и "customer_b"
  3. Использование "customer_id" из таблицы "потребителей", как внешний ключ в "customer_a" и "customer_b"

       customer 
            | 
        --------------------------------- 
        |        | 
    cusomter_a      customer_b 
    
Смежные вопросы