为什么要使密钥明确?


15

我对数据库这个主题很陌生,因此听起来似乎很无知,但是我很好奇为什么应该在表中将键显式化。这主要是为了告诉用户给定的列值(希望)在每一行中都是唯一的吗?即使没有提及,唯一性仍然应该存在。


您的意思是,如果您拥有UNIQUE密钥,那为什么还要麻烦PRIMARY密钥呢?
Vérace

1
到底为什么要宣布它们?看起来很有帮助,但是实际上有必要建立一个可以运行的数据库吗?
dsaxton

1
它们对于数据库工作不是必需的,但是它们对于数据 “工作”(即保持一致)是必需的,因为这正是您告诉数据库服务器保持信息一致的方式。
Andriy M

如果数据库知道给定的字段是键,则副作用是它可以帮助您比查找表中的所有行更快地查找包含键的行。索引是为什么数据库有用的一个非常重要的部分。
托尔比约恩Ravn的安徒生

Answers:


32

您显然建议CONSTRAINT数据库中的s应该由/访问哪个数据库的应用程序强制执行?

这是一个坏主意的原因有很多

1)如果您正在构建“自己拥有”约束“引擎”(即在您的应用程序代码中),那么您只是在模仿Oracle / SQL Server / MySQL / PostgreSQL / <。whoever ...>花费了什么写作。这些年来,他们的CONSTRAINT代码已经过数百万最终用户的测试。

2)在对您和您的团队的所有应有的尊重下,即使在几年内,您也无法做到这一点-从这里开始,仅MySQL代码就花费了4000万美元。MySQL是上述3台服务器中最便宜的,并且它们甚至都没有实现CHECK CONSTRAINT。显然,要使RI(参照完整性)完全正确是很困难的。

我曾经经常参加Oracle论坛,但我无法告诉您一些可怜的经理/程序员向他施加项目的次数,以前曾任职的天才有“聪明”的想法来做您建议的事情。

乔纳森·刘易斯(Jonathan Lewis)(他撰写了550页有关Oracle优化器基础知识的书)给出了否定的答案。他的另一本《设计灾难》中的2本(《橡树桌子的故事》-橡树桌子是一组Oracle专家)是

  1. 我们将在应用程序级别检查数据完整性,而不是利用Oracle的约束检查功能。

3)即使您可以奇迹般地正确实现RI,您也必须一次又一次地完全实现与该数据库相关的每个应用程序的RI-如果您的数据很重要,那么新的应用程序就可以了。选择这种模式将使您和您的其他程序员(更不用说支持人员和销售人员)过着不断的灭火和痛苦的生活。

您可以在此处此处此处了解更多有关为何在应用程序级别实现数据约束的疯狂之处的更多信息。

具体回答您的问题:

到底为什么要声明它们?看起来很有帮助,但是实际上有必要建立一个可以正常运行的数据库

其原因KEYS(或者PRIMARYFOREIGNUNIQUE或只是普通的INDEXES)声明的是,虽然它是不是严格必需的数据库,让他们为它的功能,它是绝对必要为他们被宣布为它的功能很好


1
感谢您的回答。我可能需要学习更多以完全理解它。(我实际上并不属于团队,我只是出于好奇而学习数据库。)
dsaxton 2015年

2
阅读几本书(Date,Garcia-Molina ...),如果您有特定的问题,请与我们联系(问题过于广泛的问题在此处被认为是题外话)。PS欢迎您到论坛:-)
Vérace

尽管我永远不会建议您在数据库中不加任何限制(您应该始终将主键和外键保持在最低限度),但可以通过让所有应用程序从共享服务中使用来避免#3(面向服务的体系结构) )。(无论如何,您可能应该考虑多个消费者,因为执行数据库中所需的每一个最后一次完整性检查也可能会引起噩梦。想想触发器始终无处不在地对表和行进行检查。)
jpmc26,2015年

10

当您在数据库中创建密钥时,DBMS引擎将对密钥属性实施唯一性约束。这至少具有三个相关目的:

  • 数据完整性:不能将重复数据输入关键属性。因此,保证了对键的任何依赖性。
  • 识别:用户能够依靠密钥来准确识别和更新数据。
  • 优化:有关哪些属性唯一的信息(元数据)可供DBMS查询优化器使用。该信息使优化器可以以某些方式简化查询执行,以便查询执行得更快。

8

我将在现有的出色答案中增加一个方面:文档。通常,很重要的一点是要查看可用于识别实体的密钥类型。唯一列的任何组合都是候选键。

在实践中,主键往往是一个特别有用的概念。

无论您是否强制执行密钥(您可能应该这样做),文档本身都是有价值的。


1
数据库图!当要求我说一些我不熟悉的软件有意义的信息时,我总是做的第一件事就是查看它是否使用关系数据库,如果使用关系数据库,则尝试创建数据库图。这将使我对应用程序使用的信息有一个很好的了解。不幸的是,我见过的90%的数据库没有声明外键,因此图表只是表的集合。推导隐式的应用程序级外键需要猜测和调整。
reinierpost

1
@reinierpost我完全同意。数据是记录和保持数据最有价值的对象,因为它可以永久保存。代码可以更改;它往往更短暂。
boot4life

@reinierpost-为一家公司提供咨询服务,该公司为一个欧洲大国的整个铁路基础设施提供软件(很大-想想数十亿个小部件),我说:“哼,我将运行查询以检查FOREIGN KEY定义以获取对系统的感觉”。我的查询返回了邮政编码!!!为确保我的SQL一定是错误的,我向一位高级程序员提到了这一点。他自豪地(毫不逊色)宣布(好像他正在生一个新生儿子一样)该系统没有任何FK,因为“所有搜索都在PRIMARY KEYs上”(无关紧要)。<Doh ...>荷马·辛普森!
Vérace

5

您应该使用CONSTRAINT而不是一些内部应用程序代码的另一个原因:

如果开发人员/ dba使用插入/更新/删除语句直接在数据库中修改数据会怎样?在这种情况下,您所有基于应用程序的不错的引用完整性将毫无用处。我知道,有些开发人员喜欢直接修改数据而不必担心RI的可能性,因为他们知道自己的工作-至少在大多数时间(但并非总是如此)

PS:当然可以创建触发器,但是它们通常很慢(与CONSTRAINTS相比)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.