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

166
我该如何在SQL中定义由两个字段组成的复合主键? 我想创建一个名为“voting”的表,其中包含字段“QuestionID”,“MemberID”和“vote”。复合主键由字段“QuestionID”和“MemberID”组成。请问应该如何实现呢?

1
(QuestionID,MemberID)将成为(复合)主。只有一个键,由两列组成。 - Draemon
4个回答

294

仅做澄清:一张表最多只能有一个主键。主键由一个或多个列(来自该表)组成。如果主键由两个或更多列组成,则称为复合主键。其定义如下:

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);

11
好的回答。只是为了澄清,QuestionID和MemberID不是单独的主键,而是它们的组合形成一个独特的对/元组。 - Peter
7
将索引添加到(MemberID, QuestionID)相比仅添加MemberID有何好处?据我所知,当使用QuestionId进行选择时,您会获得索引查找,并且还包括(QuestionId, MemeberId),因此唯一缺少的将是仅MemberId的情况。 - swalog
1
我知道这个答案很老,但是因为它在谷歌搜索中出现了...关于使用哪些列作为默认索引(或不使用)的文本存在不一致性。此外,它假设每个RDBMS都会自动在主键上创建索引,但由于没有任何标准要求这样做,可能存在一些特殊情况。 - To마SE
2
因为这两个字段都是其他表的简单(且可能是主)键,所以示例显示的是复合键而不是组合键。 - guymid

8
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`)
);

4

QuestionID将是你的主键。你可以使用MemberID作为候选键(对其进行索引),因为一个成员可能会回答多个问题,但反过来做就没有意义了。

语法:

CREATE TABLE SAMPLE_TABLE  
(COL1 integer,  
COL2 integer,  
COL3 integer,  
PRIMARY KEY (COL1, COL2));  

1
在 Oracle 数据库中,我们可以像这样实现。
CREATE TABLE Student(
  StudentID Number(38, 0) not null,
  DepartmentID Number(38, 0) not null,
  PRIMARY KEY (StudentID, DepartmentID)
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接