如何在SQL中定义复合主键?


112

如何在SQL中定义由两个字段组成的复合主键?

我正在使用PHP创建表和所有内容。我想打一个表名voting与领域QuestionIDMemeberIDvote。复合主键由字段QuestionID和组成MemberID

我应该怎么做?


“并且QuestionID和MemberID将成为主键。” (QuestionID,MemberID)将是(复合)主。只有一个键,它由两列组成。
Draemon

Answers:


229

为了澄清起见:一张表最多可以有一个主键。一个主键由一个或多个列组成(来自该表)。如果主键包含两列或更多列,则称为复合主键。定义如下:

CREATE TABLE voting (
  QuestionID NUMERIC,
  MemberID NUMERIC,
  PRIMARY KEY (QuestionID, MemberID)
);

然后,该对(QuestionID,MemberID)对表必须是唯一的,并且两个值都不能为NULL。如果执行这样的查询:

SELECT * FROM voting WHERE QuestionID = 7

它将使用主键的索引。但是,如果您这样做:

SELECT * FROM voting WHERE MemberID = 7

不会因为使用复合索引而需要使用“左侧”中的所有键。如果索引位于字段(A,B,C)上,而您的条件位于B和C上,则该索引对该查询没有用。因此,从(QuestionID,MemberID)和(MemberID,QuestionID)中选择最适合您如何使用表格的方式。

如有必要,在另一个上添加索引:

CREATE UNIQUE INDEX idx1 ON voting (MemberID, QuestionID);

5
好答案。需要澄清的是,QuestionID和MemberID不是分开的主键,而是它们的组合形成唯一的对/元组。
彼得

5
(MemberID, QuestionID)与just相比,在index上添加索引是否有好处MemberID?据我了解,使用QuestionId和进行选择时都会获得索引查找(QuestionId, MemeberId),因此唯一的缺失就是MemberId
swalog

我知道这个答案已经很老了,但是由于它是在Google搜索期间弹出的……似乎在文本中存在关于默认索引使用(或不使用)哪些列的不一致问题。此外,它假定每个RDBMS都会在主键上自动创建一个索引,但是由于任何标准都不要求它,因此可能存在一些极端情况。
To마SE 2016年

由于这两个字段都是其他表中的简单(并且可能是主键),因此该示例显示了复合键而不是复合键
Guymid '16

6
CREATE TABLE `voting` (
  `QuestionID` int(10) unsigned NOT NULL,
  `MemberId` int(10) unsigned NOT NULL,
  `vote` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`QuestionID`,`MemberId`)
);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.