在一个表中有三个主键(其中两个是外键)是否有意义?

时间:2012-05-17 00:42:41

标签: mysql sql database-design data-modeling

我创建了一个包含三个表的数据库:

Restaurant
restaurant_id (autoincrement, PK)

Owner
owner_id (autoincrement, PK)
restaurant_id (FK to Restaurant)

Deal
deal_id (autoincrement)
owner_id (FK to Owner)
restaurant_id (FK to Restaurant)
(PK: deal_id, owner_id, restaurant_id)

每家餐厅都有很多业主。我为交易选择了两张外国钥匙,所以我可以由店主或餐厅参考这笔交易。交易表有三个主键,两个是外键。它会有两个指向它的一对多关系。我的所有外键都是主键,我不知道我是否会后来这样做会后悔这样做。这种设计是否有意义,并且似乎对我想要实现的目标有益?

  

修改:我真正需要在这里完成的是当所有者登录并查看他们的帐户时,我希望他们能够查看和编辑所有相关的交易与那个特定的餐厅。并且因为每个餐馆可以有更多的所有者,所以我需要能够执行以下查询:select * from deals where restaurant_id = restaurant_id。换句话说,如果我是一个所有者并且我已经登录,我需要能够进行查询:获得与我,所有者有关的所有交易,但与所有与之相关的所有者这家餐厅。

5 个答案:

答案 0 :(得分:4)

你在术语方面遇到了一些麻烦。

一个表只能有一个一个主键。无法创建具有两个不同主键的表。您可以使用两个不同的唯一索引(非常类似于主键)创建一个表,但只能存在一个主键。

您要问的是,您是否应该拥有复合复合主键;使用多个列的主键。

你的设计没问题,但正如你所写,你可能不需要专栏deal_id。在我看来,restaurant_id和owner_id一起足以在Deal中唯一标识一行。 (如果一个所有者由于资本重组或购买另一个所有者而在一家餐馆拥有两个不同的所有权股份,则可能不是这样,但您在问题陈述中没有提到类似的事情)。

在这种情况下,deal_id主要是浪费存储。 可能是使用deal_id列的参数,如果有许多表具有指向Deal的外键,或者如果您有要向用户显示的实例,则为多个餐馆同时拥有。

如果其中一个参数影响你采用deal_id列,那么它,只有它,应该是主键。由于自动增量值本身是唯一的,所以不会添加其他两列。

答案 1 :(得分:1)

如果你有一个唯一的字段,这应该是PK,即增量字段 在这个特定的情况下,它根本没有给这个键增加更多的字段,它实际上有点影响性能(不要问我多少,你可以用它来替补)。

答案 2 :(得分:0)

没错,它有效。但是,不推荐它。

自动增量主键无外键(或主键)

在某些数据库中,您不能将多个字段用作单个主键。

复合主键或撰写主键在查询中更难处理。

复合主键查询示例:

SELECT
  D.*
FROM 
  Restaurant AS R,
  Owner AS O,
  Deal AS D
WHERE
  (1=1) AND
  (D.RestaurantKey = D.RestaurantKey) AND
  (D.OwnerKey = D.OwnerKey)

对战

单主键查询示例:

SELECT
  D.*
FROM 
  Restaurant AS R,
  Owner AS O,
  Deal AS D
WHERE
  (D.OwnerKey = O.OwnerKey)

有时,您必须将记录的外键值更改为另一个记录。例如,您的客户已经订购,交易记录已注册,他们决定从一个餐厅餐桌更改为另一个餐厅餐桌。因此,必须在“所有者”和“交易”表中更新数据。

+-----------+-------------+
|  OwnerKey | OwnerName   |
+-----------+-------------+
|      1    | Anne Smith  |
+-----------+-------------+
|      2    | John Connor |
+-----------+-------------+
|      3    | Mike Doe    |
+-----------+-------------+

+-----------+-------------+-------------+
|  OwnerKey |   DealKey   |     Food    |
+-----------+-------------+-------------+
|      1    |       1     | Hamburguer  |
+-----------+-------------+-------------+
|      2    |       2     |   Hot-Dog   |
+-----------+-------------+-------------+
|      3    |       3     | Hamburguer  |
+-----------+-------------+-------------+
|      1    |       3     |    Soda     |
+-----------+-------------+-------------+
|      2    |       1     | Apple Pie   |
+-----------+-------------+-------------+
|      3    |       3     |    Chips    |
+-----------+-------------+-------------+

如果您使用复合主键,则必须为“所有者”创建新记录,为“交易”创建新记录,复制其他字段并删除以前的记录。

如果您使用单个密钥,则只需更改Table的外键,而无需插入或删除新记录。

干杯。

答案 3 :(得分:0)

如果你想在交易表中创建2个外键,它们是餐馆和所有者,即使没有所有者或者所有者,即使没有识别,也可以在交易中存在类似于表的逻辑。表上它但你仍然可以识别表,因为它被用作所有者表上的外键,但如果你要将值放在你定义为外键的每一列上,那么我认为这将是多余的,因为我'我不知道你以后会如何使用交易表但是它的名字我觉得它会用来识别客户是否保留餐厅餐桌,看看你是如何设计数据库的已经识别了他们已保留的表,即使没有在交易表中将表指定为外键,因为使用所有者表,您可以识别他们已经保留的表,因为您在所有者表上将其用作外键您在定义表之间的关系时尽可能明智,尽可能避免冗余。 :)

答案 4 :(得分:0)

我认为这不是最好的。

首先,Deal表PK应该是deal_id。没有理由为其添加额外的列 - 如果您确实想要在另一个表中引用deal_id,则必须包含restaurant_id和owner_id,这是不好的。 deal_id是否也应该是聚簇索引(在此列上组织的a.k.a.索引)取决于数据访问模式。您的数据库是否会充满最常用于查找的data_id值,或者您主要是通过owner_id或restaurant_id查找交易?

另外,使用两个单独的FK方式你所描述的(据我所知!)将允许交易的所有者和餐馆组合不是有效的(组合不属于那个的所有者)餐厅)。在Deal表中,而不是一个FK到Owner和一个FK到Restaurant,如果你必须有两个列,那么应该只有一个复合FK到(OwnerID,RestaurantID)上的Owner表,并且Owner表中有一个对应的唯一键允许此链接。

然而,有了这样一个简单的表结构,我没有真正看到将DealID从Deal表中删除的问题,因为OwnerID总是完全暗示了RestaurantID。显然,您的交易不能仅与餐厅相关联,因为这意味着交易:所有者的1:M关系。通过所有者表格根据餐厅搜索的成本不应该那么糟糕。