我在数据库表上设置引用时遇到问题。 我有以下结构:
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建议的命名约定
一些业务规则可以更好地理解结构:
现在考虑一下 - 将team_id从球员转移到合同将解决我的问题,并且它可以保持条件“球员(如果受雇)属于俱乐部的一个球队”,但对于其他球员类型来说这将是多余的。你觉得怎么样?
答案 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关系。
编辑:继续处理关系问题。
由于球队可能只属于一个俱乐部,
为什么?在主键中包含club_id意味着如果球队改变了俱乐部,那么它将会彻底改变球队的状态。除了我不明白为什么一支球队会改变一个俱乐部这一事实,如果发生了这样的事情,球队将完全是同一个对象,完全独立于俱乐部。
否则,这将是一个可怕的概念错误。