繁体   English   中英

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

[英]Why two primary keys in a table is not allowed?

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

我不明白为什么不允许在同一表中使用两个单独的主键。 但是我们可以将一列作为主键,将另一列作为唯一键而不是null。 实际上,它具有两个不同的主键,因为我们可以使用这些键中的任何一个来清楚地标识行。 为什么第一个不允许,但第二个不允许?

我试图弄清楚逻辑,但偶然发现了科德12条规则中的规则2,

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

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

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

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

答案是

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

根据第2条规则,科德打算说什么?

如果允许多个单独的主键会发生什么问题?

你可以有许多独特KEY约束作为数据库系统允许,和许多关系较真现在看到它作为一个错误来提升这些关键之一 ,并膏抹为PRIMARY。

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

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

“主键”可以追溯到关系模型的发明者Ted Codd ,后者是基于SQL的松散基础。 Codd清楚地意识到,当关系作为变量(relvar,r-table,table等)存储在DBMS中时,它可能具有多个应强制使用的候选键。 他最初认为提名一个或多个键为“主键”可能是有益的。 从那时起(1960年代末!),RM的思维不断发展,“主键”的想法不再被认为具有潜在的益处。 关于空值,可以说类似的话:Codd继续提出两种类型的空值,即四值逻辑。 我能说什么 这个人是个天才,但并非万无一失!

令人遗憾的是,许多早期的RM思想使它融入了早期的SQL实现中,并随后被纳入SQL标准中。 并且由于“兼容性问题”,它们将永远不会从SQL标准中删除。 但是这些事情没有在SQL中正确实现。 例如,Codd没有指定relvar应该限制为一个主键,但是在SQL中实现时,现在每个表一个规则。 为什么? 早期的SQL实现者对Codd的原始论文有误解吗? 关系理论家的巧妙设计吗? 我认为是阴谋大忌!

PK和等效的NOT NULL UNIQUE约束之间的差异很小,并且不是非常有用。 例如,在SQL中指定PK时,必须指定被引用的表,但是可以省略引用列。 指定列时,它们必须“等于引用表的唯一约束的唯一列中的列名集”(即PK或任何NOT NULL UNIQUE约束)。 当从定义中删除列时,则假定引用表的PK。 如果一个表被允许具有多个PK,那么此功能实际上将不起作用。 正如我所说,这并不重要,但对于某些用户而言可能很重要。

主键具有三个属性:

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

一个表可以具有满足前两个条件的键或键组合。 您在问为什么需要第三个定义。

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

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

从规范化的角度

数据库算法背后有很多计算机科学,就像任何科学都必须做出假设一样,其中之一是数据以规范化的形式存储。 该行中的所有内容都必须取决于键(第一标准格式), 整个键(第二标准格式),并且取决于键(第三标准格式)。 当您偏离这一点时,您将获得较少的可预测性,并且通常性能较差。

行可以具有任意数量的候选键 ,每个候选键都可以满足成为主键的条件。 我想您可以将其他人称为“第二把钥匙”或“第三把钥匙”。 真的没有人这样做。 如果需要另一个值,例如自然键 ,通常将其设置为属性,而不是键。

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

从性能角度看

一个密钥对于实现规范化架构是必要且足够的。 可以设置多个密​​钥,但是它们将包含冗余数据(如果您知道一个,就知道另一个,如果您知道向谁询问),并且违反了第二种标准格式。 这也意味着每一行将占用它真正需要的更多空间。 较大的行意味着每页较少的行,这意味着性能较差,特别是考虑到主键用作集群键,并且包含在整个数据库中所有索引的叶页中。 为什么将字节花在您已经知道的事情上?

典型做法

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM