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进行比较时,使用的字节数很小.
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作为主要关键点的一些反对意见是开放的.我们依赖于该外部系统来确保唯一性,保证稳定性并验证识别.
至于745与PE,CA,这显然是错误的."爱德华王子岛"的加拿大邮政缩写和"加拿大"的ISO有向图标识了两个不同的信息,并且源自不同的来源,因此它们应该表示为两个单独的列.但让我们关注745或PE是否能成为更好的主键.
首先,数据库并不关心我们使用哪种数据类型代表"爱德华王子岛".它只是想要保证唯一性.
第二,系统的面向用户的部分可能会显示完整的扩展"爱德华王子岛",在这种情况下,应用程序无论如何都需要执行查找.这是因为同时拥有秘鲁或加利福尼亚州地址的系统的用户将会欣赏扩展名称的清晰度[1].当然,如果我们超越少数几个难题(例如状态缩写),应用程序应该在向用户显示代码时始终扩展代码.
因此,使用PE而不是745的唯一优势是它使得临时查询更容易.
第三,如果代码扩展发生变化,我们可能希望区分使用较新版本的记录.这是一个容易得多,如果745='Prince Edward Island'
和746='Prince Edward Is.'
比如果我们用PE作为主键.
第四,有编程考虑因素.例如,如果应用程序开发人员必须使用Java Enumerations提供下拉列表,则需要使用数字代码.
简而言之,熟悉自然键并不像代理键的实用性那样有用.
[1]加拿大人会知道CA代表加拿大.但MO是代表摩洛哥,摩纳哥,摩尔多瓦,黑山,蒙古还是蒙特塞拉特?实际上没有一个:它是澳门.
归档时间: |
|
查看次数: |
11645 次 |
最近记录: |