MySQL创建一对一关系
我正在创建一个数据库,这是我第一次使用它们 我有一个关于一对一通信的问题。我正在创建一个代表某项运动团队的表格 我希望每支球队只有一个比赛场地,每支球队都有自己的场地 竞技场将有许多属性(名称、座位、票价等),因此我会为它们创建一个表,即使我读到创建一对一关系的最佳实践是将所有内容放在一个表中 因为竞技场和团队是两个如此不同的概念,所以我会以如下方式将它们分为两个表:MySQL创建一对一关系,mysql,sql,database,database-design,relational-database,Mysql,Sql,Database,Database Design,Relational Database,我正在创建一个数据库,这是我第一次使用它们 我有一个关于一对一通信的问题。我正在创建一个代表某项运动团队的表格 我希望每支球队只有一个比赛场地,每支球队都有自己的场地 竞技场将有许多属性(名称、座位、票价等),因此我会为它们创建一个表,即使我读到创建一对一关系的最佳实践是将所有内容放在一个表中 因为竞技场和团队是两个如此不同的概念,所以我会以如下方式将它们分为两个表: Club -------------------- ClubID (PK) ClubName . . . ArenaID (FK
Club
--------------------
ClubID (PK)
ClubName
.
.
.
ArenaID (FK)
Arena
--------------------
ArenaID (PK)
ClubID (FK)
ArenaName
Seats
TicketPrice
此外,我认为竞技场不是自动递增的,而是与俱乐部出价相等,因为我会在创建俱乐部时自动创建竞技场。
这合理吗
我想很好地理解这种类型的关系,因为它也会用于其他情况(例如,每支球队都会有一名具有其技能的助理教练)
谢谢大家
编辑:
@凯文·鲍沃斯:我只是想说明一下比赛的情况,谢谢你的回答
@Peter Gluck您应该将竞技场视为俱乐部的一个属性,但它有其他自己的属性,我想将其与俱乐部表分开,以便更好地组织数据库。如果俱乐部想“建造”另一个竞技场,它只需更改实际竞技场的名称,就可以更改座位数和票价。但保存在数据库中的“对象”将保持不变。只会更改某些列
@布兰科·迪米特里耶维奇感谢你的详细回答。我想问你一些问题,以便更好地理解你所说的(我现在开始使用数据库)。
在第一个示例中,您没有为两个表使用两个键,一个是主键,另一个是外键,但是您只使用了一个键,同时也是主键和外键,是否正确?这两种选择有什么区别?
然后,你说如果我没有太多的团队,如果我把所有的都放在一张桌子上会更好,但我希望我会有几十(或者几百)个团队。在这种情况下,这个数字是否足以拆分表?我之所以这样说,是因为我在这个表中有不止一个一对一的关系,所以如果我把所有这些一对一的关系放在同一个表中,它会非常大
感谢大家的建议,现在我将尝试使用带有两个表和两个不同ID键的方法。
但我将在其他表中使用ypercube建议的方法 我喜欢把这些桌子分开的想法。它将使您的对象模型工作得更好 然而,关于: 此外,我还想把ArenaID不是自动递增的,而是 它等于俱乐部出价,因为我将自动创建竞技场 何时创建俱乐部。这合理吗
我会将ArenaID保留为它自己的自动整数。如果俱乐部更换竞技场会发生什么?这只是可能导致这些密钥不同步的一种情况。我有一种感觉,随着时间的推移,您将使用这种方法手动调整其中一些键。保持你的关系数据库,就是这样,保持关系数据库,不要依赖环境。你似乎很理解这些概念。您确实正在考虑适当的考虑因素来推动您的决策。只要确保你所做的假设是正确的,并且将保持正确。。(也就是说,作为B队助理教练的个人是否永远不允许成为另一个队的助理教练?如果对于所有关系,这些问题的答案始终是肯定的,那么它们确实可以建模为一对一(事实上,您可以将它们都作为单个队表的属性,而不会丢失功能),但要小心,像这样的假设很少是真实的,而且随着应用程序和数据模型的发展,这些假设注定会随着时间的推移保持真实
假设这真的是一对一,那么我考虑把它们分解成单独的表的唯一原因是性能。属性集每秒要访问数百次,而大部分属性相当稳定,访问频率要低得多。然后,您可以将访问频率较高的属性放在更小、更窄的表中,以获得更好的读写性能。分离属性纯粹是为了逻辑或组织nal美学不是我会做的…
在支持可延迟约束的DBMS上,可以使用循环外键实现真正的“1对1”:CREATE TABLE Club (
ClubId INT PRIMARY KEY
-- Other fields...
);
CREATE TABLE Arena (
ClubId INT PRIMARY KEY REFERENCES Club (ClubId)
-- Other fields...
);
ALTER TABLE Club ADD FOREIGN KEY (ClubId)
REFERENCES Arena (ClubId)
DEFERRABLE INITIALLY DEFERRED;
FKClub->Arena
在交易结束前不会强制执行,因此您可以插入Club
,然后插入Arena
,而不会遇到鸡和蛋的问题
不幸的是,您将无法在MySQL中实现真正的“1对1”关系,因为它不支持延迟约束,因此您将无法在存在真正的“1对1”所必需的循环FK的情况下插入新数据时解决鸡和蛋的问题 您甚至无法真正依赖您提出的解决方案,因为MySQL不强制执行检查约束,因此您无法强制执行
ClubId
和ArenaId
之间的相等性。可能您最好依靠应用程序逻辑来强制执行,从而使您面临潜在的错误
使用备用关键点(即唯一约束)也无济于事,因为:
CREATE TABLE Club (
ClubId INT PRIMARY KEY,
ArenaId INT UNIQUE
-- Other fields...
);
CREATE TABLE Arena (
ArenaId INT PRIMARY KEY,
ClubId INT NOT NULL UNIQUE REFERENCES Club (ClubId)
-- Other fields...
);
ALTER TABLE Club ADD FOREIGN KEY (ArenaId)
REFERENCES Arena (ArenaId);
INSERT INTO Club (ClubId) VALUES (1);
INSERT INTO Club (ClubId) VALUES (2);
INSERT INTO Club (ClubId) VALUES (3);
INSERT INTO Arena (ArenaId, ClubId) VALUES (1, 2);
INSERT INTO Arena (ArenaId, ClubId) VALUES (2, 3);
INSERT INTO Arena (ArenaId, ClubId) VALUES (3, 1);
UPDATE Club SET ArenaId = 2 WHERE ClubId = 1;
UPDATE Club SET ArenaId = 3 WHERE ClubId = 2;
UPDATE Club SET ArenaId = 1 WHERE ClubId = 3;
现在你有一个俱乐部(ClubId=1
)指向一个竞技场(ArenaId=2
),它指向另一个俱乐部(ClubId=3
)!等等
即使有效,聚集表中的二级索引也可能会很昂贵,而且很难使用
“垂直分割”理论
Club
--------------------
ClubID (PK)
ClubName
.
.
Arena
--------------------
ArenaID (PK)
ArenaName
Seats
.
.
ClubPlaysInArena
--------------------
ClubID (PK, UQ1, FK1)
ArenaID (PK, UQ2, FK2)
.
.