单个列的多个外键

时间:2009-07-27 07:43:24

标签: sql sql-server nhibernate database-design

我正在为客户/订单系统定义一个数据库,其中有两种高度不同类型的客户。因为它们是如此不同,只有一个客户表会非常难看(它充满了空列,因为它们对于一种类型来说毫无意义)。

他们的订单格式相同。是否可以在Order表中有一个CustomerId列,该列具有两个客户类型的外键?我已经在SQL服务器中进行了设置,它给了我创建关系没有问题,但我还没有尝试插入任何数据。

另外,我打算将nHibernate用作ORM,通过这样的关系可以引入任何问题吗?

7 个答案:

答案 0 :(得分:24)

不,您不能将单个字段作为两个不同表的外键。你怎么知道在哪里找钥匙?

你至少需要一个字段来告诉它是什么类型的用户,或两个单独的外键。

您还可以将所有用户共有的信息放在一个表中,并为特定于用户类型的信息设置单独的表,以便您有一个用户ID为主键的表。

答案 1 :(得分:4)

外键只能引用一个主键,所以没有。但是,您可以使用桥接表:

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

所以Order甚至没有外键;这是否可取,但是......

答案 2 :(得分:2)

我继承了一个SQL Server数据库,在那里完成了这个(在四个不相关的表的四个外键关系中使用了一个列),所以是的,它是可能的。不过,我的前任已经不在了,所以我无法问为什么他认为这是一个好主意。

他使用GUID列(&#34; uniqueidentifier&#34;类型)来避免歧义问题,并且他关闭了对外键的约束检查,因为它保证只有一个匹配。但我可以想到你应该没有多少理由,而且我没有想到你应该做的任何理由。

你的听起来像是古典&#34;专业化&#34;问题,通常通过创建包含共享客户数据的父表来解决,然后是两个包含每个客户类唯一数据的子表。您的外键将与父客户表相对,并且您根据哪个子表具有匹配条目来确定哪种类型的客户。

答案 3 :(得分:1)

您可以创建引用多个表的外键。此功能允许对表进行垂直分区,并仍保持参照完整性。但是,在您的情况下,这不适用。

您最好的选择是拥有一个包含可能列的CustomerType表 - CustomerTypeID,CustomerID,其中CustomerID是PK,然后将您的OrderID表引用到CustomerID。

拉​​吉

答案 4 :(得分:0)

两种不同类型的客户是类型和子类型的经典案例,或者,如果您愿意,还可以是类和子类。 Here是另一个问题的答案。

基本上,类表继承技术就像Arnand的答案。使用shared-primary-key技术可以让您在一列中解决由两种类型的外键创建的问题。外键将是customer-id。这将标识customer表中的一行,并在适当类型的客户类型表中标识一行(视情况而定)。

答案 5 :(得分:0)

如上所述,如果密钥是12345,您如何知道查找哪个表?我想,你可以做一些事情来确保这两个表的关键值永远不会重叠,但这太难看了,也不会让人痛苦。您可以使用第二个字段来说明它是哪种客户类型。但是,如果您要有两个字段,为什么不为客户类型1 id指定一个字段,为客户类型2 id指定另一个字段。

在不了解您的应用程序的情况下,我首先想到的是,您确实应该拥有一个通用客户表,其中包含两者共有的数据,然后还有两个附加表,其中包含特定于每种客户类型的数据。我认为必须有两个常见的数据 - 至少是名称和地址以及客户编号这些基本的东西 - 并且在表格中重复列很长时间。然后,附加表可以返回基表。由于基表有一个密钥,因此必须知道要引用哪个表的外键问题才会消失。

答案 6 :(得分:-1)

  1. 创建“客户”表,包括两种类型客户具有相同数据的所有列。
  2. 比创建表“customer_a”和“customer_b”
  3. 将“consumer”表中的“customer_id”用作“customer_a”和“customer_b”中的外键

                    customer
                        |
         ---------------------------------
         |                               |
    cusomter_a                      customer_b