【问题标题】:Composite key as foreign key (sql)复合键作为外键 (sql)
【发布时间】:2012-04-04 12:40:39
【问题描述】:

这是我关心的两张表:

CREATE TABLE IF NOT EXISTS `tutorial` (
  `beggingTime` time NOT NULL,
  `day` varchar(8) NOT NULL,
  `tutorId` int(3) NOT NULL,
  `maxMembers` int(2) NOT NULL,
  `minMembers` int(1) NOT NULL,
  PRIMARY KEY (`beggingTime`,`day`,`tutorId`),
  KEY `tutorId` (`tutorId`)
) 


CREATE TABLE IF NOT EXISTS `group` (
  `groupId` tinyint(3) NOT NULL AUTO_INCREMENT,
  `status` varchar(20) NOT NULL,
  `groupName` varchar(50) NOT NULL,
  PRIMARY KEY (`groupId`)
) 

我想在“组”中创建一个字段,该字段将链接到“教程”中的复合唯一键。所以我想我的问题是,我如何关联这些表?我是否必须为“教程”中的每个主键在“组”中创建外键字段?

【问题讨论】:

  • 你想要 1:1、1:n、n:1 还是 n:m 关系?即,多少组有多少教程?

标签: mysql sql phpmyadmin


【解决方案1】:

Per the mySQL documentation 您应该能够设置到组合的外键映射,这需要您创建多个列。

添加列并将其放入您的 group 表中

FOREIGN KEY (`beggingTime`,`day`,`tutorId`) 
    REFERENCES tutorial(`beggingTime`,`day`,`tutorId`)

正如 Steven 在下面的 cmets 中所提到的,您应该尝试重新构建它,以便教程表使用实际的主键(即使它只是一个身份代理键)。这将提高性能,因为 SQL 是为这种类型的关系而不是复合关系构建的。

【讨论】:

  • 虽然有可能,但这必须有严重的性能损失。映射到外键的主键几乎是行业标准。
  • @SteveWellens 谢谢,我根据您的评论更新了我的答案,因为您是对的,我应该首先提到这一点以及直接答案
  • 警告:引用的列必须与创建键的顺序相同。要获得正确的顺序,请右键单击外键(展开表时位于键文件夹下在 SSMS 中)和脚本创建到剪贴板。粘贴。确保您引用的列与您的键的顺序相同。
  • 我很抱歉对一个 6 年前的答案发表评论,但我不明白为什么该解决方案可能会导致“严重的性能损失”或为什么复合主键不被视为“实际主键”。 "复合主键不应该与相同大小的单个主键具有非常相似的性能吗?
  • @nwarp,我完全同意你的看法。这部分答案介于误解和都市神话之间。
【解决方案2】:

1] 重写第一个表:通过将tutorId 放在首位,它本身就自动成为一个键。事实上,除了最后一个复合列之外的所有列都成为键。

CREATE TABLE IF NOT EXISTS `tutorial` (
 `beggingTime` time NOT NULL,
 `day` varchar(8) NOT NULL,
 `tutorId` int(3) NOT NULL,
 `maxMembers` int(2) NOT NULL,
 `minMembers` int(1) NOT NULL,
 PRIMARY KEY mykey (`tutorId`,`beggingTime`,`day`)
) 

2] 拥有如此多的索引对于繁重的写入表来说是非常昂贵的。因此,请考虑在教程中使用一个附加字段作为外键;也许是一个 auto_increment record_id。给它一些想法。

【讨论】:

    猜你喜欢
    • 2021-07-24
    • 2011-07-23
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2010-12-10
    • 1970-01-01
    相关资源
    最近更新 更多