为什么不允许表中的两个主键?

时间:2018-05-01 06:13:55

标签: mysql sql database rdbms primary-key-design

我想了解为什么MySql的语法不允许在同一个表中使用两个主键的原因。我理解复合键,这与此无关。

我无法理解为什么不允许在同一个表中使用两个单独的主键。但是我们可以将一列作为主键,将其他列作为唯一列而不是null。这实际上充当了两个不同的主键,因为我们可以使用这些键中的任何一个明确地标识行。为什么不允许第一个,但后者是?

我试图找出逻辑,但偶然发现了Codd的12条规则中的规则2,其中说

  

通过使用表名,主键值和列名的组合,保证关系数据库中的每个数据(原子值)都可以在逻辑上访问。

表名,主键值和列的组合对于单个基准值应该是唯一的还是我们可以有多个组合来保证访问?为什么或者为什么不?

编辑:由于问题被确定为可能重复,我将在下面解释它是如何不同的 其他类似的问题是

  

我可以在一个表中拥有多个主键吗?

ans NO

我的问题是为什么是什么原因?

Codd打算用第2号规则说什么?

如果允许多个单独的主键,会出现什么问题?

4 个答案:

答案 0 :(得分:4)

您可以拥有与数据库系统允许的一样多的UNIQUE KEY约束,并且许多关系纯粹主义者现在认为提升这些键的一个并将其作为PRIMARY进行伪装是错误的。

逻辑上,唯一键约束和主键都实现了相同的目的 - 定义可以唯一标识行的列子集。它们也应该有资格作为外键约束的目标。

主键约束会自动应用某些默认值(例如可为空性),但没有理由不能手动将相同的约束应用于唯一键约束中包含的列。

答案 1 :(得分:3)

'主键'可以追溯到Ted Codd的发明者,the relational model的SQL基础松散。 Codd清楚地意识到,当关系作为变量(relvar,r-table,table等)存储在DBMS中时,它可能有多个应该强制执行的候选键。他最初认为提名一个或多个键作为“主要”可能是有益的。从那时起(20世纪60年代后期!),RM思想已经开始,“主要”键的概念不再被认为是潜在有益的。类似的事情可以说是零点:Codd继续提出两种类型的空值,即四值逻辑。我能说什么?这个男人是天才,但并非万无一失!

遗憾的是,很多早期的RM思想都进入了早期的SQL实现,后来又在SQL标准中得到了体现。而且由于“兼容性的枷锁”,它们永远不会从SQL标准中删除。但是这些东西在SQL中没有正确实现。例如,Codd没有指定relvar应该限制为一个主键,但是在SQL中实现每个表一个现在是规则。为什么?早期SQL实现者对Codd原始论文的误解?关系理论家能否进行明确的设计?我假设在阴谋中吵架!

PK和等效NOT NULL UNIQUE约束之间的差异很小,并不是非常有用。例如,在SQL中指定PK时,必须指定引用的表,但可以省略引用列。指定列时,它们必须“等于引用表的唯一约束的唯一列中的列名称集”(即PK或任何NOT NULL UNIQUE约束)。省略定义中的列时,则假定引用的表的PK。如果一个表被允许有多个PK,那么这个功能真的不行。正如我所说,对一些用户来说,这不是什么大问题,但也许很重要。

答案 2 :(得分:0)

主键有三个属性:

  • 值的组合是唯一的。
  • 密钥中的每个值都是NOT NULL
  • 每个表只有一个主键。

表格可以包含满足前两个条件的键或键组合。你在问为什么需要第三个定义。

定义关系逻辑是一个方便的问题,每个表都有一个"命名的"访问特定行的方法。例如,这为如何最好地定义外键关系提供了指导(使用主键)。这只是定义。

某些数据库使用主键来聚合数据 - 即对数据页上的行进行排序。鉴于数据只能以一种方式排序,这提供了一个实际的原因。

答案 3 :(得分:-2)

从标准化角度来看

数据库算法背后有许多计算机科学,就像任何科学必须做出假设一样,其中之一就是数据以normalized的形式存储。行中的所有内容都必须依赖于键(第一范式),整个键(第二范式)和除了键(第三范式)。当你偏离这一点时,你会得到更少的可预测性,通常表现不佳。

行可以包含任意数量的candidate keys,每个行都可以满足成为主键的条件。而且我想你可以把其他人称为“二级”或“三级钥匙”。真的,没人这样做。如果需要另一个值,例如一个natural key,它通常设置为属性,而不是键。

话虽如此,您可以将任意两列称为compound key,并将该键声明为主键。这样,确实有两列参与主键关系。但这会导致性能方面的问题。

从绩效角度

一个密钥对于实现规范化模式是必要且充分的。可以设置多个密​​钥,但它们将包含冗余数据 - 如果您知道一个,您知道另一个,如果您知道要询问的人 - 并且违反第二范式。这也意味着每一行都会占用它真正需要的更多空间。更大的行意味着每页的行数更少意味着性能更差,特别是考虑到主键用作聚类键并且包含在整个数据库中所有索引的叶页中。为什么要把字节花在你已经知道的东西上?

典型做法

属性中的任何其他“键”存储在定义实体的行中。例如,您可以将社会保险号存储为Employee表的属性,其中EmployeeID是主要(可能是代理)键。无论何时需要,都可以加入Employee表。 (顺便说一下,您可能希望收紧SSN的列级权限。)不要将其存储在多个位置;没有必要。

相关问题