2016-10-08 70 views
1

我试图设计一个数据库,和我的一个表是这样的:我可以在这个外键中避免“冗余”吗?

player_in_tournament

ID_tourn | ID_player | and other attributes... 

和PK由两个第一列。

在表tournament_game(表示比赛的比赛/比赛)中,我想引用player_in_tournament中的2个“对象”,所以我应该有两个外键,每个都由ID_player和ID_tour。

但是ID_tour在两个“对象”中都是相同的。

问题是改变第一个表的PK并添加ID_player_in_tournament是一个好主意,并在tournament_game表中使用它作为外键。

+0

请编辑您的问题并提供样本数据,以便我们可以看到您想表示的内容。 –

回答

1

将代理键添加到player_in_tournament表使得构建代表具有两个不同ID_tourn的玩家的tournament_game成为可能。这样做可以避免冗余,但会导致不一致。

你应该有参与两个外键三个字段 -

  • (ID_tourn, ID_player1)第一个player_in_tournament
  • (ID_tourn, ID_player2)第二player_in_tournament

注意的是,同一列ID_tourn参与了两个外键关系:

create table player_in_tournament(
    ID_tourn int 
, ID_player int 
, ... 
, primary key(ID_tourn, ID_player) 
); 
create table tournament_game(
    ID_tourn int 
, ID_player1 int 
, ID_player2 int 
, ... 
, foreign key (ID_tourn, ID_player1) 
     references player_in_tournament(ID_tourn, ID_player) 
, foreign key (ID_tourn, ID_player2) 
     references player_in_tournament(ID_tourn, ID_player) 
); 
+1

这是真的!我没有想过这个不一致的问题......并且我也不知道tournament_game的ID_tourn列可以这种方式使用(参与两个外键)。非常感谢!! :-) – p0kero

0

正如您正确猜测,这将使tournament_game表中的外键只有两列而不是四列,这将提高您需要在SQL语句中编写的联接的便利性和可读性。唯一的缺点是表格宽度的增加,但是每行只有几个字节。你可能知道,这被称为“代理键”(而不是“自然键”)。 如果这样做,请确保在“自然键”(ID_tourn, ID_player)上保留唯一键或约束,以确保这两个字段保持唯一性,并保留数据一致性。

0

这里有2个表格table player_in_tournament和tournament_game。顾名思义,tournament_game是关于比赛的表格,所以它应该有比赛ID和比赛名称以及与比赛相关的所有其他属性。另一个表player_in_tournament应该有玩家ID,玩家名称和锦标赛ID(来自tournament_game表的引用)以及与玩家相关的其他属性。这应该根据您的查询进行设计。

1

首先你有一个比赛。你给它一个你称之为ID_tourn的人造标识符。这可能是因为它没有真正的名字或数字,比如锦标赛2016Q3。 (如果是的话,你可以使用这个比赛号码,而不必人为地添加一个ID。)

然后你有球员。这里再次创建一个ID。可能是因为他们是没有任何自然识别号码的现实生活中的球员。(如果他们只是你游戏中的玩家,他们会有登录名或用户名,你可以用它来代替。)

现在你有一个联赛的球员。记录自然是由锦标赛标识符和玩家标识符来标识的。

最后你有一个比赛游戏,显然是两个比赛球员的比赛。所以一个记录将包含比赛标识符和两个球员标识符。它将包含两个外键:ID_tourn + ID_player1和ID_tourn + ID_player2。

所有这些,使用组合键和自然键(如可能的话,登录名称)是创建数据库的一个概念。另外一个是表由这些人工ID和链接表。我曾在大型数据库上工作过,并且更喜欢第一个概念,但也有其他人更喜欢全ID概念。

下面是两个比较的例子。 PK =主键,FKN =外键,PK2 =唯一约束(如第二PK)

自然键/组合键

  • 表的客户端(客户)=> PK(客户)
  • 表项(ITEM_NUMBER,说明,价格)=> PK(ITEM_NUMBER)
  • 表顺序(ORDER_NUMBER,order_date的,客户编号)=> PK(ORDER_NUMBER); FK1(client.client_number)
  • table order_item(order_number,item_number,amount)=> PK(order_number,item_number); FK1(order.order_number); FK2(item.item_number)

Artikficial标识

  • 表客户机(id_client,客户编号)=> PK(id_client); PK2(client_number)
  • 表项目(id_item,item_number,description,price)=> PK(id_item); PK2(item_number)
  • 表格顺序(id_order,order_number,order_date,client_number)=> PK(id_order); PK2(order_number),FK1(client.client_number)
  • table order_item(id_order_item,order_number,item_number,amount)=> PK(id_order_item); PK2(ORDER_NUMBER,ITEM_NUMBER); FK1(order.order_number); FK2(item.item_number)
+0

谢谢!这对我来说是一个非常有用的信息 – p0kero