我可以在一个表中拥有多个主键吗?
表可以有一个复合主键,它是由两列或更多列组成的主键.例如:
CREATE TABLE userdata ( userid INT, userdataid INT, info char(200), primary key (userid, userdataid) );
更新: 这是一个链接,其中包含复合主键的更详细说明.
您只能拥有一个主键,但主键中可以有多个列.
您还可以在表上使用唯一索引,这将有点像主键,因为它们将强制执行唯一值,并将加快查询这些值.
一个表可以有多个候选键.每个候选键都是一列或一组列,这些列是UNIQUE,一起使用,也是NOT NULL.因此,为任何候选键的所有列指定值足以确定有一行符合条件,或者根本没有行.
候选键是关系数据模型中的基本概念.
如果一个表中存在多个密钥,则通常的做法是将一个候选密钥指定为主密钥.通常的做法是使表的任何外键引用主键,而不是任何其他候选键.
我推荐这些实践,但关系模型中没有任何内容需要在候选键中选择主键.
这是主要问题和@ Kalmi问题的答案
拥有多个自动生成列有什么意义?
下面的代码具有复合主键.其中一列是自动递增的.这只适用于MyISAM.InnoDB将生成错误" ERROR 1075(42000):表定义不正确;只能有一个自动列,必须将其定义为键 ".
DROP TABLE IF EXISTS `test`.`animals`; CREATE TABLE `test`.`animals` ( `grp` char(30) NOT NULL, `id` mediumint(9) NOT NULL AUTO_INCREMENT, `name` char(30) NOT NULL, PRIMARY KEY (`grp`,`id`) ) ENGINE=MyISAM; INSERT INTO animals (grp,name) VALUES ('mammal','dog'),('mammal','cat'), ('bird','penguin'),('fish','lax'),('mammal','whale'), ('bird','ostrich'); SELECT * FROM animals ORDER BY grp,id; Which returns: +--------+----+---------+ | grp | id | name | +--------+----+---------+ | fish | 1 | lax | | mammal | 1 | dog | | mammal | 2 | cat | | mammal | 3 | whale | | bird | 1 | penguin | | bird | 2 | ostrich | +--------+----+---------+
如其他人所指出的,可以具有多列主键.但是应该注意的是,如果你有一些不是由密钥引入的功能依赖,你应该考虑规范你的关系.
例:
Person(id, name, email, street, zip_code, area)
可能存在功能依赖性id -> name,email, street, zip_code and area
但通常a zip_code
与a相关联,area
因此之间存在内部功能依赖性zip_code -> area
.
因此,可以考虑将其拆分为另一个表:
Person(id, name, email, street, zip_code) Area(zip_code, name)
这样它与第三种正常形式一致.
主键是非常不幸的符号,因为"初级"的内涵和与逻辑模型有关的潜意识联想.因此我避免使用它.相反,我指的是物理模型的代理键和逻辑模型的自然键.
重要的是,每个实体的逻辑模型至少具有一组"业务属性",其包括实体的密钥.Boyce,Codd,Date等在关系模型中将这些称为候选键.然后,当我们为这些实体构建表时,它们的候选键在这些表中成为自然键.只有通过那些自然键,用户才能唯一地识别表中的行; 因为代理键应始终对用户隐藏.这是因为代理键没有商业意义.
然而,在没有代理键的情况下,我们的表的物理模型在许多情况下效率低下.回想一下,非聚集索引的非覆盖列只能通过密钥查找(通常)找到聚簇索引(忽略作为堆积实现的表).当我们的可用自然密钥很宽时,这(1)扩大了我们的非聚簇叶节点的宽度,增加了存储要求,并且对非聚集索引的搜索和扫描进行了读取访问; (2)减少聚集索引的扇出,增加索引高度和索引大小,再次增加聚簇索引的读取和存储要求; (3)增加了我们的聚簇索引的缓存要求.从缓存中追逐其他索引和数据.
这是一个小的代理键,被指定为RDBMS作为"主键"证明是有益的.当设置为聚类键时,为了用于从非聚集索引和相关表中的外键查找中查找聚簇索引的键,所有这些缺点都消失了.我们的聚簇索引扇出再次增加以减少聚簇索引的高度和大小,减少聚簇索引的缓存负载,减少通过任何机制访问数据时的读取(无论是索引扫描,索引搜索,非聚簇键查找还是外键查找)并降低表的聚簇索引和非聚簇索引的存储要求.
请注意,仅当代理键很小且聚类键时才会发生这些好处.如果GUID用作聚类键,则情况通常比使用最小可用自然键时更糟.如果表被组织为堆,则8字节(堆)RowID将用于键查找,这比16字节GUID更好但性能低于4字节整数.
如果由于业务限制必须使用GUID,那么搜索更好的群集密钥是值得的.例如,如果一个小的站点标识符和4字节的"站点序列号"是可行的,那么该设计可能比作为代理键的GUID具有更好的性能.
如果堆的结果(可能是散列连接)使得该首选存储成为更广泛的集群密钥的成本,则需要将其平衡到权衡分析中.
考虑这个例子::
ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
其中元组" (P_Id,LastName) "需要唯一性约束,并且可能是冗长的Unicode LastName加上4字节整数,因此需要(1)声明性地将此约束强制实施为" ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED(P_Id) ,LastName) "和(2)分别声明一个小的代理键作为聚簇索引的" 主键 ".值得注意的是,Anita可能只希望将LastName添加到此约束中以使其成为覆盖字段,这在聚簇索引中是不必要的,因为所有字段都被它覆盖.
SQL Server将主键指定为非聚簇的能力是一个不幸的历史情况,因为"首选自然或候选键"(来自逻辑模型)与"物理存储中的查找键"的含义相混淆模型.我的理解是,最初SYBASE SQL Server总是使用4字节的RowID,无论是作为堆还是聚簇索引,作为物理模型中的"存储中的查找键".
(已经研究了很多)
只能有1个主键。
但是您可以有多个备用键。
简单来说就是这种情况:
有可能有多个候选键(最少列,唯一标识行)在表中。
专门选择了一个候选密钥,称为主密钥
所有其他候选键称为备用键
主键和备用键都可以是复合键(2列或更多列)
来源:
https : //en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key