![]() |
1
12
不,您的ID可以同时是一个代理密钥(这意味着它不是“从应用程序数据派生的”,例如一个人工密钥)。 和 它也应该是您的主密钥。 主键用于唯一、安全地标识表中的任何行。它必须是稳定的、唯一的,并且不能为空——一个“人工”ID通常具有这些属性。 我通常建议不要对主键使用“自然”或实际数据-不是 真正地 150% 当然是 从未 要改变吗??例如,瑞士的SSN相当于女性每次结婚(或离婚)时都会发生变化——这几乎不是一个理想的候选人。它也不能保证是独一无二的…… 为了让自己省去所有的痛苦,只需要使用一个代理(人工)ID,它是系统定义的、唯一的,并且永远不会改变,也永远不会有任何应用意义(除了作为您的唯一ID之外)。 ScottAmbler在这里有一篇很好的文章,它包含了所有不同的键及其含义的“词汇表”——你会发现自然键、代理键、主键等等。 |
![]() |
2
6
首先,代理键是在数据库中人为生成的键,作为表中每一行的唯一值,它不依赖于表中的任何其他属性。 现在,这个短语 主键 是一条红鲱鱼。密钥是主密钥还是备用密钥并不意味着什么。关键是钥匙的用途。键可以提供两个基本上彼此不一致的功能。
所以答案很简单… 总是 (无论您在何处关注数据完整性/一致性)使用自然密钥,必要时使用两者!当自然键是复合键、长键或不够稳定时,添加备用代理键(例如自动递增整数),用作子表中FK的目标。但是,在丢失表的数据一致性的风险下,不要从主表中删除自然键。 为了让这个水晶清晰可见,让我们举个例子。 假设你有一张有银行账户的桌子…自然密钥可以是银行路由号和银行帐号。为了避免在Transactions表中的每个事务记录中使用此双组合键,您可能会决定在BankAccount表上放置一个人工生成的代理键,它只是一个整数。但你最好保留自然钥匙!如果没有,如果您也没有复合自然键,那么您很容易在表中得到两行,如下所示
现在,哪一个是对的? 在下面的评论中,对马克来说,能够“识别 行 “?在我看来根本不好,因为我们需要识别的是 银行账户 行代表! 标识行 只对内部数据库技术功能(如查询中的联接)或FK约束操作很重要,如果需要,这些功能应该使用代理键,而不是自然键。 您是对的,因为对自然键的糟糕选择,或者有时甚至是对自然键的最佳可用选择,可能不是真正唯一的,或者不能保证防止重复。但是,任何选择都比没有选择要好,因为它至少会防止为选择为自然键的属性中的相同值重复行。通过适当选择关键属性,这些问题可以保持在最低限度,但有时它们是不可避免的,必须加以处理。但这样做还是比允许不正确、不准确或冗余的数据进入数据库要好。 至于“易用性”,如果您使用的所有自然键都是约束重复行的插入,而您使用的是另一个、代理项、键作为FK约束的目标,那么我看不到任何易用性问题。 |
![]() |
3
4
数据库纯粹主义者之所以对代理键大发雷霆,是因为如果使用不当,它们可以允许数据复制,这是良好的数据库设计注定要消除的一个缺点。
例如,假设我有一个邮件列表的电子邮件地址表。我希望它们是独一无二的,对吧?在相同的电子邮件地址中输入2、3或n项是没有意义的。如果我使用
但是,如果我有一个字段
非纯粹主义者之所以需要它,是因为它使使用标准化代码变得容易,因为您可以依赖于引用具有整数值的单个数据库行。如果你有一把自然的钥匙,比如说,
很明显这个例子过于简化了,但它说明了这一点。 |
![]() |
4
3
哇,你用这个问题打开了一罐虫子。数据库纯粹主义者会告诉你永远不要使用代理键(就像上面提到的那样)。另一方面,代理键可以有一些巨大的好处。我一直在用它们。 在SQL Server中,代理项通常是SQL Server为您生成的自动增量标识值。它与表中存储的实际数据没有关系。与之相反的是一把天然钥匙。例如社会保险号码。这确实与表中存储的数据有关系。自然键有好处,但在我看来,使用代理键的好处大于自然键。 我注意到在您的示例中,您有一个主键的GUID。您通常希望远离作为主键的guid。它们大而笨重,通常可以随机插入数据库中,导致严重的碎片化。 兰迪 |
![]() |
5
1
用户表
使用A
登录表
除非你打算暴露
|
![]() |
6
0
将一个整数ID作为主键(即使它实际上并不意味着什么)的背后的想法是为了索引。然后您可能会将自然键定义为表上的唯一约束。这样你就可以得到两个世界中最好的。使用ID字段进行快速索引,并且每一行仍然保持其自然的唯一性。 也就是说,有些人用天然钥匙发誓。 |
![]() |
7
0
实际上有三种钥匙可以谈。主键是用来唯一标识表中每一行的。代理键是使用该属性创建的人工键。自然密钥是从实际生活数据中派生出来的主密钥。 在某些情况下,自然密钥可能不方便,因此可以创建一个代理密钥用作外键等。例如,在日志或日记中,pk可能是条目的日期、时间和全文(如果可以同时添加两个条目)。显然,每次想要标识一行时都要使用所有这些内容是一个坏主意,因此您可以创建一个“日志ID”。它可能是一个序列号(最常见的),也可能是日期加上一个序列号(如20091222001),或者它可能是其他东西。但是,有些自然钥匙也可以作为主钥匙使用,例如车辆VIN号、学生ID号(如果不重复使用),或者在连接表的情况下,连接两个表的PK。 这只是表键选择的概述。有很多事情需要考虑,尽管在大多数商店中,你会发现它们都与“向每个表添加一个标识列,这是我们的主键”匹配。然后你会遇到所有的问题。 在您的情况下,我认为日志项的logentryID似乎是合理的。用户表的ID是否为FK?如果不是这样,那么我可能会质疑ID和logentryID是否在同一个表中,因为它们是多余的。如果是的话,我会把名字改成用户名或者类似的东西。 |
![]() |
Community wiki · SQL语法新手 1 年前 |
|
KateMak · 是否将多行中的多列与唯一id组合? 1 年前 |
![]() |
Karuna · SQL中列内的筛选器[重复] 1 年前 |
![]() |
Irvan Affandy · 为另一个选择选择声明的键 1 年前 |
![]() |
Community wiki · 这个MySQL语句出了什么问题? 1 年前 |
![]() |
Community wiki · 优化从同一表中提取的多列的查询 1 年前 |