主键的devise标准是什么?
select好的主键,候选键和使用它们的外键是非常重要的数据库devise任务 – 与科学一样多的艺术。 devise任务有非常具体的devise标准。
什么标准?
考虑主键的标准是:
- 唯一性
- 不可约简性 (密钥的子集没有唯一标识表中的一行)
- 简单 (所以关系表示和操作可以更简单)
- 稳定性 (不应该经常改变)
- 熟悉 (对用户有意义)
什么是主键?
主键是唯一标识数据行/logging的东西。 它也可以是多列,这就是所谓的复合。
能力改变
由于主键通常用于外文引用,因此应尽可能保持稳定。 数据库中的所有数据都是可变的,提供某人正在连接具有适当权限的帐户。 这就是为什么数据库提供了定义CASCADE ON DELETE和CASCADE ON UPDATE的能力 – 同步参考依赖关系而不必禁用约束。
自然还是人工/代孕?
理想情况下,你需要一个自然的钥匙。 一个自然的关键是现有的数据,唯一标识你正在build模的实体。 例如,美国的缩写是一个很好的自然关键,因为缩写是一致的,每个人都知道它们:
US_STATE_PRIMARY_KEY US_STATE -------------------------- AL Alabama AK Alaska AZ Arizona AR Arkansas CA California
不要太努力去find一个自然的钥匙。 他们很less存在。 美国国名不太可能会改变,但这似乎是合理的。
实际上,主键通常是人为的(通常由数据库function生成)。 这些通常是数字或GUID,它们被认为是人造的,因为它们自己 – 没有什么可以将它们的价值与它们唯一标识的信息联系起来。 销售收据总是有编号的,因为它没有什么自然之处,而且也用于审计 – 收据编号的差距引起怀疑。 为了演示如何任意编号,下面是US状态表,但使用主键列US_STATE_CODE的整数:
US_STATE_PRIMARY_KEY US_STATE -------------------------- 100 Alabama 101 Alaska 102 Arizona 103 Arkansas 104 California
没有要求在一开始的价值; 一些商店使用这个作为安全措施来阻止SQL注入。 该值是按照州名的字母顺序排列的,但不能保证。 但是与自然键不同的是,如果状态名称改变了 – 只有一列需要更新。
单列与复合
理想情况下,一列将是主键,但根据手头的数据作出决定 – 不要仅仅为了具有单列而组合列。 如果你一起做shoehorn数据,使用一个字符很容易分开数据(虽然操作这样做将不能利用索引,如果存在的话)。
性能
从性能的angular度来说,整数是最好的,因为它们提供了一个体面的值范围,当与五个或更多字符的VARCHAR进行比较时,使用的字节数很less。
数据库devise从概念数据模型(如实体关系图)开始,并以数据库模式或模式结束。 实体映射到表; 在这个过程中,一个实体可以被拆分成几个表格,几个实体可以被合并到一个表格中,并且可能出现新的表格(例如,实现多对多关系的相交表格)。
在ERD中,实体具有主键。 这些是自然的关键,那就是它们是实体的属性。 对于PERSON实体,它可能是SocialSecurityNumber。 对于ORDER实体,如果可能是OrderRef对于INVOICE实体,它可能是InvoiceNo。 在第一种情况下是一个现实生活中的标识符; 在第二种情况下,它是一个丑陋格式的智能钥匙(2010 / DEF / 000023); 在第三种情况下,这是一个单调递增的数字,因为这是目前的纸面系统所使用的。
自然钥匙可以是奇特的。 我曾经在一个数据库devise上工作过,分析师用一个关键字(FullName,Address,Sex,DateOfBirth,DistinguishingCharacteristics)指定了CUSTOMER实体,因为两个同名,出生date和性别的人可以同住地址。
实体主键的特征是:
- 独特
- 熟
- 稳定(推定)
- 最小(一个或多个属性,但是尽可能less)
当谈到数据库表的主键时,自然键并不总是合适的。
有很多原因不使用SSN作为物理主键。 公民个人信息的保护其实是最重要的,但个人的数字也是可以改变的。 主键应该是不变的。
智能钥匙是愚蠢的。 他们实际上是复合键压缩成一个单一的列。 它们被更好地表示为单独的列,这不仅仅是因为search密钥的单个元素经常需要。 此外,这些键的格式可以改变。
一般情况下,复合键作为主键是一种痛苦,因为我们必须将多个列作为外键级联。 当孩子的主键被定义为父母主键中的序列号时,这会加剧。 有一些系统在那里依赖表inheritance一个从父母的九列外键,当他们有自己的两个数据列很less。 有时这种inheritance可能是有用的,但大多数情况下这只是一个麻烦。
实体主键的特征是:
- 独特
- 适当的(无意义的)
- 保证稳定
- 最小的,通常是一列(交叉表除外)
所以除非候选密钥是一个无意义的标识符(例如发票号),否则一个表应该有一个合成密钥(AKA代理键)。 这可以是一个单调递增的数字或根据您的需要的GUID。 关于交集表,如果它们没有其他属性或从属表,那么用合成主键(AKA复合关键字)replace复合主键是没有价值的。
关键的是:我们仍然执行候选键 。 这意味着对父表中的这些列(SSN,OrderRef)应用UNIQUE约束。 这是因为合成关键字唯一标识了一个表中的一行,它并不唯一地标识数据。
关于熟悉
熟悉是一个curl的。 当涉及到在概念数据模型中识别主键时,这是一个重要的考虑因素,但在数据库devise方面却没那么有用。
在commnet @bbadour提供了两个对比的例子:
{3296013,840082470,Bob Badour,745} versus {840082470,Bob Badour,PE,CA}
并提出了这样一个问题:
“3296013达到了什么目标还没有达到840082470,这正好是我在加拿大任何一所高中的学习成绩的主要关键。”
那么,840082470就像一个发票号码。 它本身是一个无意义的数字串。 如果我们正在devise的系统属于加拿大高等教育领域,那么它肯定是可以接受的候选关键。 然而,由于这是外部中央系统显然拥有的一个关键(原谅我不理解加拿大的学术体系),所以对于SSN作为主要关键的一些反对意见是开放的。 我们依靠外部系统来保证唯一性,保证稳定性和validation身份。
至于745与PE,CA ,这显然是错误的。 加拿大邮政“爱德华王子岛”的缩写和“加拿大”的ISO字母组合标识了两个截然不同的信息,并且源自不同的来源,所以它们应该表示为两个单独的列。 但让我们关注745还是PE做出更好的主键。
首先,数据库并不关心我们用代码来表示“爱德华王子岛”的数据types。 它只是想保证唯一性。
第二件事,系统的面向用户的部分可能会显示完整的扩展“爱德华王子岛”,在这种情况下,应用程序无论如何将需要执行查找。 这是因为一个系统的用户也持有来自秘鲁国家或加利福尼亚州的地址,因此将会对扩展名称的清晰度有所了解[1]。 当然,如果我们超越了一些难以处理的情况(比如州级缩写),应用程序在向用户显示时总是应该展开代码。
因此,使用PE而不是745的唯一好处是它使临时查询更容易。
第三件事,如果代码扩展发生变化,我们可能要区分使用较新版本的logging。 如果745='Prince Edward Island'
和746='Prince Edward Is.'
745='Prince Edward Island'
,这会容易745='Prince Edward Island'
746='Prince Edward Is.'
比如果我们使用PE作为主键。
第四件事,有编程方面的考虑。 例如,如果应用程序开发人员必须使用Java枚举提供下拉列表,则他们需要数字代码。
简而言之,自然键的熟悉程度不如代理键的实用性。
[1]加拿大人会知道CA代表加拿大。 但是MO是否代表摩洛哥,摩纳哥,摩尔多瓦,黑山,蒙古或蒙特塞拉特呢? 其实都不是澳门。
候选关键字是一组不可分割的唯一属性(不可简化,意味着在不失去唯一性属性的情况下,不能从关键字中删除属性)。
当select要实现的候选键时的其他标准是:简单性,稳定性,熟悉性。
这三个标准是重要的考虑因素,但不一定是关键的基本属性。 例如,执行一个经常变化的密钥可能是可取的,也是相当合理的。 例如:用户login名称必须是唯一的,但用户可以随意更改,只要它保持唯一。
主键是候选键。
主键是唯一标识实体的键。 当你select一个主键时,最好的select几乎总是一个代理键,除了唯一识别它外,它与这个实体完全没有任何关系。
就是这样。 假设有一个很less见的边缘情况下,主键可能是一个自然的关键,但我从来没有见过一个有效的。
我们大多数人使用一个32位自动增量整数作为主键。 另一个很好的select(在某些情况下)是UUID。
嘿。 它再次打开。 开始。
(1)select好的候选键。
它不涉及数据库devise者select候选键。 数据库devise者有责任确保用户通知的所有唯一性要求将被强制执行。 所以是“select”候选键的用户。
有两种情况我可以想到,放松一下这个明确的立场。
一个是,如果用户说某种types的“video”或“audio”(或其他)属性是唯一的。 实际上实施这一点可能是不可行的,devise者有责任向用户指出(因为指出audio和video内容的“独特性”是一个非常有争议的主题也是他的责任,这种属性值的唯一性,即使由系统强制执行,仍然有很大的机会不是用户想要的唯一性)。
其次是由于不同的逻辑devise都可以解决同样的问题,图片如何变得混乱。 如果D1和D2都是解决相同问题的有效devise,则可能是用户施加的某个给定的唯一性规则可以使用D1中的密钥而不是D2中的密钥来强制执行。 从这个angular度来看,“select候选键”可以被解释为“select特定的devise,使得使用键可以实现给定的唯一性规则”。 但这不是你问的问题。
(2)select好的主键。
不久前,Darwen发表了一个问题:“从其他人当中选出一个人作为”主要“的原因是什么? 除此之外,没有什么东西出来了:“build议这个特定的关键字是引用这个relvar时使用的首选关键字”。 我怀疑他们没有find足够的说服力来改变他们早先的“没有钥匙比其他人更独特”的决定。
但是,尽pipe如此,还是有一些合理的理由来把一个特定的关键字作为“主要”,但我想以下的考虑适用:
- 使用这个主键的可能性或适当性也作为例如物理devise中的聚类键。
- 并因此,必须改变一些现有主键的值的可能性。 高度稳定的关键值比易变性的关键值更可取。
- 在日常运营中自然使用某些此类密钥的业务的百分比。
- 如果物理编码键值所需的空间显着不同,哪一个编码尺寸最小。
您对Erwin的回答是:“我同意select一个主键只是指定一个候选键作为外键引用的首选,但即使我们完全取消了名称”主键“,devise者仍然必须select哪个候选键传播到另一个候选键如果用户用一个不稳定的组合键来标识一个被严重引用的关系,那么你是否打算暗示devise者没有select一个简单而稳定的关键字?或者使用简单而稳定的关键字来引用关系?你的候选人关键部分似乎暗示了 – bbadour 8小时前“
你原来的问题是关于“主键”。 现在,您将焦点转移到键和外键上。 一个关键是完整性约束,所以唯一的标准是一个最小的属性集合在关系中必须是唯一的(唯一性和不可约性)。 如果我们把注意力转移到外键上,那么简单性,稳定性和熟悉程度就是所有候选键在参照关系中select的标准。 可能会有更多的候选键符合这个标准,或多或less有相同的扩展。 如果我们看一下熟悉程度,一个候选键可能对一组用户非常熟悉,而不是另一个候选键更熟悉的另一个组。 考虑数据库的不同视图或子图。 这第二组用户应该select一个不同的候选键作为参考(作为外键)。 如果你坚持每个关系只有一个“主键”,那么我必须要问一个关键是什么使得一个关键比其他关键更重要。 我认为不应使用术语主键。 至less在逻辑层面上。 此外,术语“外键”没有很好的select(外键不是键,而是引用)。
所以,我认为Erwin关于“主要”键的评论非常重要。 或者至less这是我对他的意思的解释。
你同意吗? 如果是这样,你会改变你原来的问题:“什么是关键的devise标准,以及从可用的候选键中select外键的标准是什么?”? 如果没有,为什么?
问候,卡洛斯
主键是为特殊处理select的候选键,所以首先我们必须看候选键的属性。 一个或多个列的集合是一个候选键,如果它具有以下两个属性:
唯一性:候选键必须唯一标识表中的每一行。 没有一个表可能包含具有相同值的候选关键字的两行。
不可预知性:从候选键中删除任何列必须违反uniqness属性。 换句话说,候选密钥中没有列的子集本身就是候选密钥。
如果不存在候选键,并且有时即使存在候选键,则通常使用自动递增整数列来创build代理键,或者使用其他技术来构build代理键。 这个代理键现在也是候选键。
select可用的候选键并将其中的一个指定为主键通常是有用的。 通常应用的第一个标准是简单性,指示具有最less列的候选键。 然而,还有其他潜在的标准,比如熟悉度,熟悉的值比不熟悉的值更有用,稳定性更好,稳定的键比易于改变的键更麻烦。 然而,这些标准严格限于关系模型的范围之外,往往相互冲突,往往是为了处理实施的限制。
我想说前两个概念“独特性”和“不可约性”是比主键的基本属性更less的devise标准,而后者的“简单性”,“熟悉性”和“稳定性”这些概念则是更恰当的标签devise标准,它们涉及权衡和主观性。
为什么select主键? 简单性和熟悉性不仅是select可用的候选键的标准,而且也是为什么我们应该select一个主键。 如果表中有多个候选键,则如果指向该表的所有外键引用相同的候选键,则简化操作。 此外,select一个特定候选键的行为将有助于熟悉。
什么标准?
PRIMARY KEY
是定义实体的东西,只是实体而不是实体。
-
你可以把它从外面的世界。 说一个明星号码来识别一个明星(好例子),或者一个
SSN
来识别一个人(坏例子)。在这种情况下,你依靠外界。
- 所有的人都有
SSN
吗? (他们不)。 -
SSN
是独一无二的吗? (他们不是)。 -
SSN
可以分配给另一个人吗? (它可以)。
- 所有的人都有
-
你可以在你的模型中使用
AUTOINCREMENT
或GUIDs
或其他来生成它。在这种情况下,你依靠自己和你的数据库技能。
- 模型中的所有人都有
ID
吗? (是的,他们这样做,否则他们不会在ID NOT NULL
的表中)。 - 这些
ID's
独一无二的吗? (是的,他们是,PRIMARY KEY
约束照顾它)。 - 他们可以分配给其他人吗? (不,它们不能,它们要么是不可重复的,要么是自动递增的)。
或者另一组答案:
- 模型中的所有人都有
ID
吗? (不,他们没有,人们的桌子被意外地丢弃了,尽pipe还有一些其他的信息)。 - 这些
ID's
独一无二的吗? (不,我们没有正确合并两个版本的数据库)。 - 他们可以分配给其他人吗? (是的,我们错误地重置了
AUTOINCREMENT
)。
- 模型中的所有人都有
最重要的是代孕钥匙是一个永远伴随着你的盛宴。 您始终可以创build代理键:地球上没有任何东西可以阻止您声明AUTOINCREMENT
字段。 但是到目前为止,并不是所有的东西都有某种人人都认同的标识符。
然而,一个好的自然钥匙怎么强调都不为过。
Guide Star Catalog
数据库最有可能比你更可靠地备份, US
国家代码列表总是可以从内存中恢复。
(不太清楚如何解释这个问题,听起来像是一个测验,或者是从教科书中寻找一个“正确”的答案,我将把这个问题解释为一个更实际的问题,因此我的build议如下。 )
至less在MS SQL世界中,关于正确的主键的讨论不可避免地包含在关于表的适当聚集索引的讨论中。 两者不一定是相同的,但是它们是默认的,对于很多表格,使两者相同通常是一个好主意。
为了我们在这里讨论的目的,重要的是区分两者:
PRIMARY KEY是唯一标识行的字段或字段组合。
集群索引是表示表的物理顺序的字段或字段的组合。 (同样,我正在谈论MS SQL Server,不知道其他RDBS如何处理这个问题)
我的其余讨论的关键是知道,自SQL 7.0以来, 聚簇索引键被用作所有非聚簇索引的行标识符。 这意味着select好的集群密钥的许多相同的标准与select好的主密钥相同。
我们先来看一个好的聚集索引的标准(来自Kimberly Tripp的优秀文章 )。 聚集索引应该是:
- 唯一 – 否则用作其他索引的行标识符
- 缩小 – 此键用于其他索引,因此应尽可能缩小
- 静态 – 如果键值发生变化,则引用变为无效并需要更新
- 不断增加的 – 为了减less物理表碎片添加新的行
显而易见的是前3个主键也是很好的标准。 #4是一个奖金,可以减less表碎片随着表的增长。
一个GUID作为一个主要的关键,就像这样stream行,实际上没有这些标准中的两个(狭窄和不断增加)。 因此,在大多数情况下,不build议将其作为PK /聚集索引(请参阅Kim的相关文章 )
只有一个,为每个表(身份/自动编号)或类似的用户将永远不会看到,所以你可以做任何必要的事情,当他们需要现在和将来。
我要在这里说一些没有预料到的事情。
所有他们在数据库中教授的有关规范化和密钥的东西在select主键方面都是错误的。
对于范围查询,主键是特殊的,因此,如果您的主键范围查询是您的主键,则没有例外。
如果您的主导范围查询不在候选关键字上,您最终得到的主键不是唯一性的! 这有时被称为聚集索引,因为没有索引,所以这是一个误用。
现在,规范化和候选键是非常重要的,你至less要对它们中的一些执行唯一的约束。 但是不要分配主键,因为它是自然的关键。 实际上,这比定义一个索引和一个唯一的约束要慢。 仅基于范围查询来定义主键。
记住,实际上有主键没有限制。 没有主键的表被称为堆表,并且没有内部sorting或插入顺序内在sorting。
编辑:范围查询的定义:
范围查询是一个查询,它是一个ORDER BY查询,或者包含一个大于或小于运算符。 我们感兴趣的是这些查询运行的列。 其基本思想是基于一个或两个端点的边界条件,范围查询从表中提取几个(从几十到几百个甚至几千个,但不是全部)行。
还有另一种范围查询,那就是你有一个外键到另一个表,并且一个操作是select所有匹配的外键。 这实际上也是一个范围查询,虽然不是很明显。