MySQL 中的复合主键示例

Posted

技术标签:

【中文标题】MySQL 中的复合主键示例【英文标题】:Composite Primary Keys example in MySQL 【发布时间】:2012-09-20 14:26:15 【问题描述】:

最近遇到了 mysql 本身和 MySQL 中的 Composite Primary Keys 的话题,特别是它的用处和优缺点,来自site

我想玩这个,所以我以这种方式创建了三个表:

CREATE TABLE person(
    personId INT(11) NOT NULL,
    personName VARCHAR(20) NOT NULL,
    PRIMARY KEY(personId)
)

CREATE TABLE language(
    languageId INT(11) NOT NULL,
    languageName VARCHAR(20) NOT NULL,
    PRIMARY KEY(personId)
)

CREATE TABLE personLanguage(
    personId INT(11) NOT NULL,
    languageId INT(11) NOT NULL,
    description VARCHAR(20) NOT NULL,
    PRIMARY KEY(personId, languageId),
    FOREIGN KEY (personId) REFERENCES person(personId) ON UPDATE CASCADE ON DELETE CASCADE,
    FOREIGN KEY (languageId) REFERENCES language(languageId) ON UPDATE CASCADE ON DELETE CASCADE
)

我可以将数据插入到人员和语言表中——直截了当,我的问题是:

    对于 personLanguage 表,我是否只需要插入描述列,而其他列是自动引用的,还是我还需要在 personLanguage 表中插入其他两列的值

    是否有可能在插入其他两个表中的数据后自动更新 personLanguage 表中的 personId 和 languageId,据我所知,何时以人员或语言完成某些更新/删除表它在 personLanguage 表的两列上反映相同

    如何获取三个表相关的数据,例如我需要知道 personId=1 的人说哪种语言?它也是使用连接的直接查询还是因为我使用复合主键而有其他方法可以做

很多问题困扰着我,我真的找不到一个完整的工作示例来检查使用复合主键的确切利弊。如果有人可以使用我的示例详细说明这一点,那将非常有帮助。

我知道我已经问了一些基本的,一些毫无意义的问题,但请耐心等待,并就这个话题提出一些好的看法

【问题讨论】:

【参考方案1】:

对于 personLanguage 表,我是否只需要插入描述 列,而其他列被自动引用,或者我 需要在 personLanguage 中插入其他两列的值 桌子也是如此

是的,您需要插入所有三列才能完全有效。否则数据库将不知道您尝试将此记录绑定到什么人或语言。

是否有可能更新 personId 和 languageId personLanguage 表中的其他两个数据自动 插入表,据我所知,何时完成一些更新/删除 在人称表或语言表中,两者都反映相同 personLanguage 表中的列

您可以通过插入触发器执行此操作,但这可能没有任何意义。所以,假设您刚刚输入了一种新语言——比如法语。您根本不需要在 personLanguage 表中输入任何值,因为您的现有用户可能不希望获得法语信息。同样的情况也适用于创建一个新人。你可能有很多种语言。大多数人不会说大多数语言,所以同样,您不希望将记录自动输入到 personLanguage 表中。

至于更新个人和语言的记录,KEYS 不应该改变。这就是为什么你会做这样的事情。一旦 Bob 或 Alice 被分配了一个 personId,他们就是那个 Id。为法语分配语言 ID 后,它应该始终是该语言 ID。

如何获取三个表相关的数据,例如我需要 知道 personId=1 的人说哪种语言?难道也是 使用连接的直接查询或有其他方法吗 因为我使用复合主键

嗯,这是个棘手的问题。如果您尝试获取 personId=1 使用的所有语言,则加入非常简单。

select pl.personId, l.languageId, l.languageName 
  from personLanguage pl
    join language l on l.languageId = pl.languageId
    where pl.personId = 1

如果您想弄清楚您应该与该人交流哪种语言,情况会变得更加复杂,因为该人可能没有定义任何 personLanguages。如果您可以接受空值,则可以使用外连接,但您需要定义查询以便只返回一种语言。

【讨论】:

【参考方案2】:

    对于 personLanguage 表,我是否只需要插入描述列,而其他列是自动引用的,还是需要在 personLanguage 表中插入其他两列的值

    如果引用的表中存在现有键,您只能将值插入personLanguage。这意味着您必须先填充personlanguage,然后才能将值插入personLanguage。但是,如果您有一个 NULLable 字段,您可以这样做,但它会违反唯一复合键。

    是否有可能在插入其他两个表中的数据后自动更新 personLanguage 表中的 personId 和 languageId,据我所知,何时以人员或语言完成某些更新/删除表它在 personLanguage 表的两列上反映相同

    您指定的约束 (ON UPDATE CASCADE) 意味着当 personlanguage 中的引用值发生更改时,它将自动更新 personLanguage 中的这些值。但是,不能违反personLanguage 上的PRIMARY KEY 约束。

    如何获取三个表相关的数据,例如我需要知道 personId=1 的人说哪种语言?它也是使用连接的直接查询还是因为我使用复合主键而有其他方法可以做

    由于这是一个基本示例,因此实际上没有必要这样做。在扩展形式中,您可以使用显式JOINs 来获取表之间的数据。

还有一些想法......

复合键通常用于元组(或集合)中的引用。这意味着当您在 table1 上拥有一个复合键 (col1, col2) 时,这将引用 table2 上的一个复合键 (col1, col2)。

【讨论】:

以上是关于MySQL 中的复合主键示例的主要内容,如果未能解决你的问题,请参考以下文章

如何识别任何 Mysql 数据库表中的复合主键?

mysql的联合主键与复合主键区别

问题解决:MySQL 从复合主键中删几个键

联结表中的复合主键 - Sequelize

ALTER TABLE 添加复合主键

mysql外键复合主键[重复]