主键的设计标准是什么?

bba*_*our 8 database database-design foreign-keys data-modeling primary-key

选择好的主键,候选键和使用它们的外键是一项非常重要的数据库设计任务 - 与科学一样多的艺术.设计任务具有非常具体的设计标准.

标准是什么?

OMG*_*ies 18

什么是主键?

主键是唯一标识数据行/记录的东西.它也可以是多列,称为复合.

改变的能力

因为主键通常用于外部引用,所以它应该尽可能稳定.数据库中的所有数据都是可变的,前提是某人正在使用具有适当权限的帐户进行连接.这就是为什么数据库提供定义CASCADE ON DELETE和CASCADE ON UPDATE的能力 - 同步参照依赖关系而不必禁用约束.

自然或人工/代理?

理想情况下,您需要一个自然键.自然键是唯一标识您正在建模的实体的现有数据.例如,美国州的缩写是一个很好的自然关键,因为缩写是一致的,每个人都知道它们:

US_STATE_PRIMARY_KEY  US_STATE
-------------------------- 
AL                    Alabama
AK                    Alaska
AZ                    Arizona
AR                    Arkansas
CA                    California
Run Code Online (Sandbox Code Playgroud)

不要太努力找到自然的钥匙.它们很少存在.美国国家名称不太可能改变,但这似乎是合理的.

实际上,主键通常是人为的(通常由数据库功能生成).这些通常是数字或GUID,它们被认为是人为的,因为它们本身 - 没有任何东西可以将它们的价值与它们唯一识别的信息联系起来.销售收据总是有编号的,因为它没有任何关系,它也适用于审计 - 收据数量的差距引起了怀疑.为了演示任意编号是什么,这里是美国州表,但是使用主键列的整数US_STATE_CODE:

US_STATE_PRIMARY_KEY  US_STATE
-------------------------- 
100                   Alabama
101                   Alaska
102                   Arizona
103                   Arkansas
104                   California
Run Code Online (Sandbox Code Playgroud)

没有要求在一个地方启动价值; 一些商店将此作为一种安全措施来阻止SQL注入.该值是基于州名的字母顺序的顺序,但不能保证.但与自然键不同,如果状态名称发生更改 - 只需要更新一列.

单列与复合

理想情况下,一列将是主键,但是根据手头的数据做出决定 - 不要仅为了拥有单个列而组合列.如果你一起做鞋拔数据,使用一个字符可以轻松地分离数据(尽管这样做的操作将无法利用索引(如果存在)).

性能

从性能角度来看,整数是最好的,因为它们提供了一个合适的值范围,并且当您与五个或更多字符的VARCHAR进行比较时,使用的字节数很小.

  • @bbadour:这是主键的第一课 - 您是否拥有唯一标识记录的自然值?如果答案为否,则需要使用人工值(整数,GUID). (4认同)
  • @bbadour:如果我理解正确的话,这是外键.外键可以是主键,通常位于多对多表中. (3认同)
  • 如果您打算使用自然键,请务必选择一个静态键.电话号码可能是唯一的,但也可以更改.同样,公司可能会更改其员工ID格式.甚至可以更改或复制SSN(在极少数情况下).状态缩写可以是合理的主键,只要您将其仅用作主键而不是用于显示,因为大写约定可以改变. (3认同)
  • 我不知道为什么你认为我很好斗或为什么你认为我没有掌握一些东西.也许你把自己的缺点投射到我身上?在我更正的例子中,第1个元组遵循始终使用代理键的规则,第2个元组进行有效的设计权衡.你能看一下745的意思吗?3296013实现了840082470尚未达到的目标,这恰好是我在加拿大任何一所高等院校的学术记录的主要关键.一个好的设计是正确的,优雅的和有用的.我认为第一个示例元组在2个计数上失败. (2认同)
  • 如果你给出了明确,明智,正确和有用的答案,我会给出答案.你还没有.如果我不能从你写的东西中提取任何明智的意义,我就无法明智地回应.我建议那些认为他们从你所写的内容中提取合理意义的人,只是将自己的假设投射到它上面以填补空白.你称之为攻击你的答案,我称之为诚实地承认我自己的局限. (2认同)
  • 我只能建议你在你的答案中寻找缺陷而不是我的缺陷.通过任意数量的措施,您可以更好地分配资源. (2认同)
  • @Alexander,你假设1)该人知道如何加入,2)该人有权查询被引用的表,3)该人知道如何找到被引用的表,4)数据仍然在数据库中执行连接,5)不需要发现连接所产生的成本.如果你的任何假设都是假的,你所谓的一切都是毫无意义的. (2认同)
  • @bbadour - 电子表格中没有固有的方法来强制执行数据库理论的任何元素.为什么要使用不能强制执行主键基本方面的工具的人谈论良好主要选择的属性?我们假设某人询问数据库设计元素是否会使用某种数据库管理系统,这真的很疯狂吗? (2认同)

Bra*_*adC 15

考虑主键的标准是:

  • 唯一性
  • 不可简化性(密钥的任何子集都没有唯一标识表中的行)
  • 简单(以便关系表示和操作可以更简单)
  • 稳定性(不应经常更改)
  • 熟悉(对用户有意义)


APC*_*APC 8

Database design starts with a conceptual data model (such as an entity relationship diagram) and finishes up with a database schema or schemas. Entities are mapped to tables; in this process one entity may be split into several table, several entities may be merged into a single table and new tables may arise (for instance, intersection tables to implement many-to-many relationships).

在ERD中,实体具有主键.这些是自然键,即它们是实体的属性.对于PERSON实体,它可能是SocialSecurityNumber.对于ORDER实体,如果可能是OrderRef对于INVOICE实体,它可能是InvoiceNo.在第一种情况下,这是一个真实的标识符; 在第二种情况下,它是一种丑陋格式的智能钥匙(2010/DEF/000023); 在第三种情况下,它是单调递增的数字,因为这是当前基于纸张的系统使用的数字.

自然键可以是幻想.我曾经在数据库设计上工作过,分析师用同一个名称,出生日期和性别的两个人生活在同一个基础上,指定CUSTOMER实体的密钥为(FullName,Address,Sex,DateOfBirth,DistinguishingCharacteristics).地址.

实体主键的特征是:

  • 独特
  • 稳定的(假定的)
  • 最小(一个或多个属性,但必要的少)

对于数据库表的主键,自然键并不总是合适的.

有很多理由不使用SSN作为物理主键.保护公民的个人数据实际上是最重要的,但个人的数字也可以改变.主键应该是不变的.

智能钥匙很笨.它们实际上是压缩成单列的复合键.它们更好地表示为单独的列,尤其是因为它是搜索键的单个元素的常见要求.此外,这些键的格式可以改变.

通常,复合键是主键,因为我们必须将多个列级联为外键.当孩子的主键被定义为父母主键中的序列号时,这会加剧.在那里有一些系统,当它们只有两个自己的数据列时,它们从父项继承一个九列外键.有时这种继承可能很有用,但大多数情况下这只是一个麻烦.

实体主键的特征是:

  • 独特
  • 适当的(无意义的)
  • 保证稳定
  • 最小的,通常是一列(交叉表除外)

因此,除非候选键是无意义的标识符(例如InvoiceNo),否则表应该具有合成键(AKA代理键).根据您的需要,这可以是单调递增的数字或GUID.关于交集表,如果它们没有其他属性或从属表,则用合成主键替换复合主键(AKA复合键)没有任何价值.

关键是:我们仍然强制执行候选键.这意味着在父表中的那些列(SSN,OrderRef)上应用UNIQUE约束.这是因为合成键唯一地标识表中的行,它不唯一地标识数据.


关于熟悉度

熟悉是一个卷曲的.当我们在概念数据模型中识别主键时,这是一个重要的考虑因素,但在数据库设计方面它没那么有用.

在一个commnet @bbadour中提供了两个截然不同的例子:

{3296013,840082470,Bob Badour,745} versus {840082470,Bob Badour,PE,CA}  
Run Code Online (Sandbox Code Playgroud)

并提出问题:

"3296013实现了840082470尚未达到的目标,这恰好是我在加拿大任何一所高等院校的学术记录的主要关键."

好吧,840082470就像发票号码.它本身就是一个无意义的数字串.如果我们设计的系统属于加拿大高等教育领域,那么它当然可以作为候选关键.然而,因为它显然属于外部中央系统所拥有的关键(原谅我不了解加拿大的学术体系),对SSN作为主要关键点的一些反对意见是开放的.我们依赖于该外部系统来确保唯一性,保证稳定性并验证识别.

至于745PE,CA,这显然是错误的."爱德华王子岛"的加拿大邮政缩写和"加拿大"的ISO有向图标识了两个不同的信息,并且源自不同的来源,因此它们应该表示为两个单独的列.但让我们关注745PE是否能成为更好的主键.

首先,数据库并不关心我们使用哪种数据类型代表"爱德华王子岛".它只是想要保证唯一性.

第二,系统的面向用户的部分可能会显示完整的扩展"爱德华王子岛",在这种情况下,应用程序无论如何都需要执行查找.这是因为同时拥有秘鲁或加利福尼亚州地址的系统的用户将会欣赏扩展名称的清晰度[1].当然,如果我们超越少数几个难题(例如状态缩写),应用程序应该在向用户显示代码时始终扩展代码.

因此,使用PE而不是745的唯一优势是它使得临时查询更容易.

第三,如果代码扩展发生变化,我们可能希望区分使用较新版本的记录.这是一个容易得多,如果745='Prince Edward Island'746='Prince Edward Is.'比如果我们用PE作为主键.

第四,有编程考虑因素.例如,如果应用程序开发人员必须使用Java Enumerations提供下拉列表,则需要使用数字代码.

简而言之,熟悉自然键并不像代理键的实用性那样有用.

[1]加拿大人会知道CA代表加拿大.但MO是代表摩洛哥,摩纳哥,摩尔多瓦,黑山,蒙古还是蒙特塞拉特?实际上没有一个:它是澳门.

  • 这是罕见的,但也有一些重复的SSN(我想社会保障管理部门在某些时候修复它) (3认同)