2

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

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

我试图弄清楚逻辑,但偶然发现了 Codd 的 12 条规则中的第 2 条,上面写着

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

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

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

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

答案是NO

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

Codd 打算通过第 2 条规则说什么?

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

4

4 回答 4

5

您可以拥有数据库系统允许的尽可能多的 UNIQUE KEY 约束,并且许多关系纯粹主义者现在认为提升这些键之一并将其涂为 PRIMARY 是错误的。

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

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

于 2018-05-01T06:50:05.477 回答
3

“主键”可以追溯到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,那么这个功能就真的行不通了。正如我所说,这没什么大不了的,但对某些用户来说可能很重要。

于 2018-05-01T10:54:45.930 回答
0

主键具有三个属性:

  • 价值观的组合是独一无二的。
  • 键中的每个值都是NOT NULL.
  • 每个表只有一个主键。

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

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

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

于 2018-05-01T10:37:53.237 回答
-2

从标准化的角度来看

数据库算法背后有很多计算机科学,就像任何科学都必须做出假设一样,其中之一就是数据以标准化的形式存储。行中的所有内容都必须依赖于键(第 1 范式)、整个键(第 2 范式)和除了键(第 3 范式)之外的所有内容。当您偏离这一点时,您将获得更少的可预测性并且通常会表现不佳。

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

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

从性能角度

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

典型实践

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

于 2018-05-01T07:14:10.803 回答