2010-04-15 81 views
18

我在学习如何使用键和打破所有表中所有行的必须具有SERIAL类型ID的习惯。同时,我也在进行多对多的关系,因此要求协调关系的任何一列的唯一值都会妨碍这一关系。MySQL中的多列主键5

如何定义表上的主键,以便任何列中的任何给定值都可以重复,只要所有列中的值的组合都不会完全重复?

+0

可能的重复[如何正确创建复合主键 - MYSQL](http://stackoverflow.com/questions/5835978/how-to-properly-create-composite-primary-keys-mysql) – 2015-11-23 20:53:29

+0

不能是3年后发布的东西的副本。 – Kaji 2015-11-23 20:55:28

+0

http://meta.stackexchange.com/questions/147643/should-i-vote-to-close-a-duplicate-question-even-though-its-much-newer-and-ha ;-) – 2015-11-23 21:09:17

回答

39

CREATE TABLE Syntax页面引用:

主键可以是一个多列 索引。但是,不能使用 规范中的 PRIMARY KEY关键字属性创建 多列索引。这样做只标记 单列作为主要。您必须使用单独的主键 KEY(index_col_name,...)子句。

像这样可用于多列主键:

CREATE TABLE 
    product (
     category INT NOT NULL, 
     id INT NOT NULL, 
     price DECIMAL, 
     PRIMARY KEY(category, id) 
    ); 

13.6.4.4. FOREIGN KEY Constraints

+0

Shouldn'你是否在你的例子的PK(类别,ID,价格)中包含价格?他要求提供'任何专栏'和'跨所有专栏'? ...然后添加一个严厉的评论关于这是不是最理想的,缓慢的,并且在现实生活中从不需要? (YES!我在这里挑剔:-) – lexu 2010-04-15 05:09:00

+0

我同意。所有列应该在那里 – fiacobelli 2012-07-16 18:06:10

+0

在我的情况下完全不起作用。例如,如果我使用不同的类别,但是使用相同的ID,仍然会显示重复的密钥。 – 2014-05-06 03:40:38

17

主键是唯一地(一定和足够)识别您的实体的域概念在类似的实体中。只有当关键字的一部分引用了另一个域实体的特定实例时,复合(多列)主键才有意义。

比方说,你有一个个人收藏的书籍。只要你一个人,你就可以数它们,并为每个数字分配一个数字。该号码是图书馆域的主键。

现在你想合并你的图书馆和邻居的图书馆,但仍然能够区分图书所属的人。该域现在更广泛,主键现在是(owner,book_id)。

因此,制作每个主键组合不应该是您的策略,而应该在需要时使用它。

现在有关MySQL的一些事实。如果你定义了一个组合主键并且希望RDBSM为你自动增加ID,你应该知道MyISAM和InnoDB行为之间的区别。

假设我们想要一个有两个字段的表:parent_id,child_id。我们希望child_id是自动增加的。

MyISAM将在具有相同parent_id的记录中自动增加,而InnoDB将在整个表内自动增加。

在MyISAM中,您应该将主键定义为(parent_id,child_id),并将InnoDB定义为(child_id,parent_id),因为autoincremented字段应该是InnoDB中主键最左侧的组成部分。

+1

这是一个杰出的答案。 – Dakatine 2017-09-26 15:41:15

1

主键是行的唯一值。包含价格是没有意义的,价格可能会改变。想象一下,如果你必须改变大范围的价格,那么所有这些主键值都会改变。真是一团糟!