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

yqyhoc1h  于 2021-06-21  发布在  Mysql
关注(0)|答案(4)|浏览(427)

我想了解mysql语法为什么不允许在同一个表中使用两个主键的原因。我理解复合键,这与此无关。
我不明白为什么同一个表中不允许有两个独立的主键。但我们可以将一列作为主键,而将另一列作为唯一且不为null的列。实际上,它有两个不同的主键,因为我们可以使用这些键中的任何一个来清楚地识别一行。为什么第一个是不允许的,而后面是允许的?
我试图弄明白其中的逻辑,但无意中发现了codd的12条规则中的第2条
关系数据库中的每一个数据(原子值)都通过表名、主键值和列名的组合来保证在逻辑上是可访问的。
对于单个数据值,表名、主键值和列的组合应该是唯一的,还是可以有多个组合来保证访问?为什么?为什么不?
编辑:由于问题被确定为可能的重复,我将在下面解释它与其他类似问题的不同之处
我可以在一个表中有多个主键吗?
答案是否定的。
我的问题是为什么?原因是什么?
根据第二条规则,codd打算说什么?
如果允许多个单独的主键,会出现什么问题?

aurhwmvo

aurhwmvo1#

主键有三个属性:
价值观的结合是独一无二的。
键中的每个值都是 NOT NULL .
每个表只有一个主键。
表可以具有满足前两个条件的as-may键或键组合。你在问为什么需要第三种定义。
为了方便定义关系逻辑,每个表都有一个访问特定行的“命名”方法。例如,这为如何最好地定义外键关系(使用主键)提供了指导。这只是一个简单的定义。
有些数据库使用主键对数据进行聚类,也就是对数据页上的行进行排序。鉴于数据只能以一种方式排序,这就提供了一个实际的原因。

sbtkgmzw

sbtkgmzw2#

您可以拥有数据库系统所允许的任意多个唯一的键约束,现在许多关系纯粹主义者将提升其中一个键并将其指定为主键视为一个错误。
从逻辑上讲,唯一键约束和主键都实现了相同的目的—定义列的子集,通过这些子集可以唯一地标识行。他们也应该有资格成为外键约束的目标。
某些默认值(如nullability)由主键约束自动应用,但没有理由不能将相同的约束手动应用于包含在unique key约束中的列。

fhity93d

fhity93d3#

“主键”可以追溯到ted codd,他是sql松散基础的关系模型的发明者。codd清楚地意识到,当一个关系作为一个变量(relvar、r-table、table等等)存储在dbms中时,它可能有多个应该强制执行的候选键。他最初认为将一个或多个键指定为“primary”可能是有益的。从那时起(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,那么这个功能就真的不起作用了。正如我所说,这不是什么大问题,但对某些用户来说可能很重要。

inkz8wg9

inkz8wg94#

从规范化的Angular
数据库算法背后有很多计算机科学,就像任何科学都必须做出假设一样,其中之一就是数据以规范化的形式存储。行中的所有内容都必须依赖于键(第一范式)、整个键(第二范式)以及除键(第三范式)之外的任何内容。当你偏离这一点,你会变得不可预测,通常表现不佳。
一行可以有任意数量的候选键,每个候选键都可以满足作为主键的条件。我想你可以把其他的叫做“二级键”或“三级键”,真的没有人会这么做。如果需要另一个值,例如自然键,则通常将其设置为属性,而不是键。
也就是说,您可以将任意两列称为复合键,并将该键声明为主键。这样,确实有两列参与主键关系。但这会导致性能问题。
从性能Angular
一个键对于实现一个规范化的模式是必要的和足够的。可以设置多个密钥,但它们将包含冗余数据—如果您知道其中一个,那么您知道另一个,如果您知道该询问谁—并且违反了第二范式。这也意味着每一行将占用更多它真正需要的空间。较大的行意味着每页的行数较少,这意味着性能较差,特别是考虑到主键用作集群键,并且包含在整个数据库的all-in索引的叶页中。为什么要把字节花在你已经知道的东西上?
典型做法
将任何其他“键”作为属性存储在定义实体的行中。例如,可以将social security number存储为employee表的一个属性,employeeid是主键(也可能是代理键)。无论何时需要,都可以加入employee表(顺便说一句,您可能希望收紧ssn的列级权限。)不要将其存储在多个位置;没有必要。

相关问题