引用复合主键的一部分

时间:2014-06-01 16:00:01

标签: sql database-design ddl composite-primary-key

我在数据库表上设置引用时遇到问题。 我有以下结构:

CREATE TABLE club(
    id INTEGER NOT NULL,
    name_short VARCHAR(30),
    name_full VARCHAR(70) NOT NULL
);
CREATE UNIQUE INDEX club_uix ON club(id);
ALTER TABLE club ADD CONSTRAINT club_pk PRIMARY KEY (id);

CREATE TABLE team(
    id INTEGER NOT NULL,
    club_id INTEGER NOT NULL,
    team_name VARCHAR(30)
);
CREATE UNIQUE INDEX team_uix ON team(id, club_id);
ALTER TABLE team ADD CONSTRAINT team_pk PRIMARY KEY (id, club_id);
ALTER TABLE team ADD FOREIGN KEY (club_id) REFERENCES club(id);

CREATE TABLE person(
    id INTEGER NOT NULL,
    first_name VARCHAR(20),
    last_name VARCHAR(20) NOT NULL
);
CREATE UNIQUE INDEX person_uix ON person(id);
ALTER TABLE person ADD PRIMARY KEY (id);

CREATE TABLE contract(
    person_id INTEGER NOT NULL,
    club_id INTEGER NOT NULL,
    wage INTEGER
);
CREATE UNIQUE INDEX contract_uix on contract(person_id);
ALTER TABLE contract ADD CONSTRAINT contract_pk PRIMARY KEY (person_id);
ALTER TABLE contract ADD FOREIGN KEY (club_id) REFERENCES club(id);
ALTER TABLE contract ADD FOREIGN KEY (person_id) REFERENCES person(id);

CREATE TABLE player(
    person_id INTEGER NOT NULL,
    team_id INTEGER,
    height SMALLINT,
    weight SMALLINT

);
CREATE UNIQUE INDEX player_uix on player(person_id);
ALTER TABLE player ADD CONSTRAINT player_pk PRIMARY KEY (person_id);
ALTER TABLE player ADD FOREIGN KEY (person_id) REFERENCES person(id);
-- ALTER TABLE player ADD FOREIGN KEY (team_id) REFERENCES team(id); --this is not working

它给了我这个错误:

Error code -5529, SQL state 42529: a UNIQUE constraint does not exist on referenced columns: TEAM in statement [ALTER TABLE player ADD FOREIGN KEY (team_id) REFERENCES team(id)]

如您所见,团队表具有复合主键(club_id + id),该人通过合同引用俱乐部。 人员对于玩家和其他员工类型有一些共同的属性。

一个俱乐部可以拥有多个团队。雇员必须与俱乐部签订合同。球员(是人的规范) - 如果被分配 - 可以分配给俱乐部的一个球队。

有没有更好的方法来设计我的结构?我想将club_id从团队的主键中排除,但我想知道这是否是唯一的方法。感谢。

更新1

我希望只在俱乐部内拥有身份证明,因此只要他们属于不同的俱乐部,多个球队就可以拥有相同的身份。有可能吗?

更新2 更新了philip建议的命名约定

一些业务规则可以更好地理解结构:

  • 一支球队可以有1支球队(主阵容,预备队,青年队) 或者A队,B队......只有球队可以比赛,而不是俱乐部)
  • 一支球队只属于一个俱乐部
  • 玩家是一类人(其他类型(工作人员)是侦察员,教练等,所以他们不需要属于特定的团队,只有俱乐部,如果雇用的话)
  • 人可以与1个俱乐部签订0..1合同(这意味着他就业或失业)
  • 球员(如果受雇)属于俱乐部的一支球队

现在考虑一下 - 将team_id从球员转移到合同将解决我的问题,并且它可以保持条件“球员(如果受雇)属于俱乐部的一个球队”,但对于其他球员类型来说这将是多余的。你觉得怎么样?

2 个答案:

答案 0 :(得分:2)

当一个表中的子行必须是另一个(引用的)表中的子行时,这是一个包含依赖项(IND)。例如,玩家team_id引用团队ID(不是团队中的密钥)。当存在IND 时,引用的子行是一个键,即外键(FK)。例如,玩家person_id引用人员ID(亲自关键)。在SQL中,FOREIGN KEY声明表明存在IND,并且引用的列是唯一的。 (即由PRIMARY KEY或UNIQUE声明)。 (所以它实际上意味着“外来超级密钥”。)在SQL中,我们理想地通过CHECK约束声明IND(当不存在FK时)。 (但是DBMS不支持CHECK)。即检查team_id是否在团队中投射到id的玩家。但是你试图声明一个SQL FK。它失败了,因为正如错误消息所示,团队ID不是唯一的。


(请注意团队及其团队ID之间的区别commented。因为团队ID不能识别团队,所以您应该只谈论由团队ID和俱乐部识别的团队.OOP必须区分< em>不仅世界各地的团队和世界上的团队ID(某种字符串),而且“team_id”指针/编程语言的参考值。它是{{ 3}} id“是一个坏名字,因为单独的团队ID并不能识别团队。我们可以使用世界上使用的术语。”

但实际上你想要的东西比你的玩家表team_id IND和player_id FK强。即检查team_id在俱乐部中配对的玩家,其中club_id与person_id合作配对,即person_id。

如果您的设计涉及名单(club_id,team_id,player_id),而且玩家没有team_id且可能也没有合同,那么这些复杂的约束实际上是不必要的。

不,我们不能从“人通过合同引用俱乐部”的架构中“看到”。 (而且这句话很难表达你的意思。)我们无法从表和键中说出来。 每个表都包含满足由其列名参数化的某些语句的行;你必须提供这些陈述。例如对于玩家:人[person_id]在由[team_id]&amp;一些俱乐部。您还必须提供所有业务规则,以限制可能出现的情况。例如:一个人最多可以签约一个俱乐部。一支球队最多只属于一个俱乐部。如果没有语句,用户(也不是我们)就无法使用数据库,如果没有语句和业务规则,您(也不是我们)无法确定约束。把它们写出来。

答案 1 :(得分:0)

什么应该是唯一的是团队表中的team_id列。目前你所做的事情意味着只要有不同的俱乐部,就可以重复一个队友,这是不正确的。

club的FK已经注意到你提到的0-n关系。

编辑:继续处理关系问题。

由于球队可能只属于一个俱乐部,

  1. 关系应该用外键表示(club_id指向俱乐部表)
  2. 主键不应包含club_id
  3. 为什么?在主键中包含club_id意味着如果球队改变了俱乐部,那么它将会彻底改变球队的状态。除了我不明白为什么一支球队会改变一个俱乐部这一事实,如果发生了这样的事情,球队将完全是同一个对象,完全独立于俱乐部。

    否则,这将是一个可怕的概念错误。