我在大学学习的时候,他们教我们数据库基础,基础和规则,其中最重要的规则之一是约束(主键,外键),以及如何建立1-m,1-1,mn关系.
现在,当我转向真实的商业环境时,他们告诉我:你应该忘记你所学的一切;没有约束,所有这些关系都是逻辑的,没有主键,没有外键,你可以通过代码来做你的约束。
我不知道谁是对的:我在学术生活中学到了什么,或者我将在新的真实商业生活中学到什么。你怎么看?
我在大学学习的时候,他们教我们数据库基础,基础和规则,其中最重要的规则之一是约束(主键,外键),以及如何建立1-m,1-1,mn关系.
现在,当我转向真实的商业环境时,他们告诉我:你应该忘记你所学的一切;没有约束,所有这些关系都是逻辑的,没有主键,没有外键,你可以通过代码来做你的约束。
我不知道谁是对的:我在学术生活中学到了什么,或者我将在新的真实商业生活中学到什么。你怎么看?
如果有人告诉我忽略数据库中的键和约束,我会立即忽略它们并继续我的业务。
主键、外键和约束的存在是有原因的。使用它们。它们将使您的生活更轻松,并使您的数据库更易于理解(并且通常更高效)。
我使用数据库的时间越长,我就越欣赏约束。从长远来看,它们为我节省了很多时间。只有受信任的约束才能确保数据 100% 的有效性。
我写了一章关于约束的使用与其他确保数据完整性的方法,可在此处免费下载
如果您认为约束仅与主键和外键有关,那么实际上您一开始并没有学到很多“基础知识”。
我建议您看一下Hugh Darwen的“关系数据库理论简介”,该书可在线免费获得。至少你从那个人那里得到了关于“基础”的真正教育。
我认为约束可以帮助您获得干净的数据。性能有时会得到改善。在某些情况下,性能可能会受到约束的影响。但是,答案不是消除约束。您有一种称为“非规范化”的方法来帮助您处理性能问题(前提是您的查询已经优化)。在这种情况下,您始终可以创建非规范化汇总表。
那些叫你“忘掉所学”的人,是不是也告诉你,他们在驾驶课上学过的交通规则都忘记了?
当您有可能破坏您的数据的用户(即任何用户)访问数据库时,数据库约束是一个好主意。我倾向于保留外键约束,以确保在我的数据库中编辑数据的任何人都知道其他表依赖于当前表中的数据。
好吧,确实很少有终极真理,而且许多商业上成功的产品都避开了声明的参照完整性 (DRI),这也是事实。
另一方面,如果您关心数据库中的数据,几乎没有比通过 DRI 更好的方法来保护该数据的完整性。
如果你把这一切都留给最上面的代码,你就会寄希望于没有人会通过任何其他方式访问数据库。如果他们这样做,将无法阻止数据损坏(孤立行、不一致和不合逻辑的数据)。
你学到的不仅仅是学术上的东西。但是,是的,它有时就像柏拉图的乌托邦。这是您的数据库可以处于的完美状态,理想的设计。但这种理想的设计并不总是可行的。
约束应尽可能接近数据库数据。这样想吧。如果您在代码中编写了约束,然后您想迁移到不同的语言/平台并且在您的一个约束中出现错误怎么办?这将是灾难性的。PK、FK、约束等被广泛使用。它们已经使用了 30 多年。因此,它们不是垃圾,但在某些情况下,它们只是无法管理。例如,如果你是谷歌,你不能仅仅依靠关系模型在几毫秒内给出答案。
因此,基于速度和稳定性等要求,我们有时也会复制数据,我们不使用 PK,或者我们不建立关系等。但只有当我们正在寻找特定的东西并且我们知道我们会失去什么时通过这样做。
归根结底,关系模型仍然只是一个模型。这是一种表示事物的方式。一种非常成功的方式,但它不是天赐之物,因此在某些情况下必须妥协。
我花了很多时间来修复那些认为约束属于应用程序代码的无能者产生的垃圾数据。如果一个数据库的设计没有这些必需的东西,它就会有坏数据。对运行了几年的此类系统进行快速检查,您会发现孤立的记录和缺少所需的信息等。
当我在课堂上时,我们使用原始 SQL 访问表,并且有很多原始 SQL 或等效的。在这些情况下,约束通常是好的。
但是,有些系统使用数据库作为后端,并且这些数据库只能由该特定软件系统访问。在这种情况下,软件应该跟踪必要的关系和约束,并且数据库充当冗余检查,不能提供良好的反馈并降低性能。
数据库约束是多余的,因为附加系统需要自己维护约束。反馈是违反了某个数据库约束。如果一个程序能够处理这样的反馈,它就能够进行自己的检查。性能成本应该是显而易见的。
这些约束在开发或测试系统上仍然有用,但是当系统投入生产时,他们所能做的就是在出现问题时使系统崩溃,而这通常正是您不希望在像这样的大型系统中发生的事情那。
主键很重要。您需要一种唯一标识行的方法。
但是,根据我的经验,如果您正确地将数据库访问封装在类中(即,从数据库读取/写入对象),通常不需要约束。是的,如果 10 种不同语言的 50 个不同应用程序使用同一个数据库,我可能会使用它们。但是,如果它是一个应用程序,或者是一组共享源代码库的通用应用程序,我宁愿将所有数据库操作逻辑放在一个地方,以使应用程序更易于维护。存储过程也是如此,但如果您编写旨在处理各种数据库的代码,它们在数据库系统之间存在额外的可移植性问题。