在数据库设计中是否真的需要外键?

据我所知,外键(FK)是用来帮助程序员以正确的方式操作数据的。假设一个程序员实际上已经在以正确的方式做这件事,那么我们真的需要外键的概念吗?

外国钥匙还有其他用途吗? 我是不是漏掉了什么?

43706 次浏览

外键有助于加强数据级别的参照完整性,还可以提高性能,因为默认情况下它们通常被编入索引。

外键还可以帮助程序员使用 ON DELETE CASCADE之类的东西编写较少的代码。这意味着,如果您有一个包含用户的表和另一个包含订单或其他内容的表,那么删除用户可以自动删除指向该用户的所有订单。

我无法想象设计一个没有外键的数据库。如果没有它们,最终肯定会出错并损坏数据的完整性。

严格来说,它们不是 需要,但是好处是巨大的。

我相当肯定 雾虫在数据库中没有外键约束。我很想知道 Fog Creek 软件公司团队是如何构建他们的代码来保证他们永远不会引入不一致性的。

如果没有外键,如何判断不同表中的两条记录是相关的?

我认为你指的是参照完整性,在没有父母记录的情况下,子女记录是不允许创建的。这些通常被称为外键约束-但是首先不要与外键的存在混淆。

可以将外键视为约束,

  • 帮助维护数据完整性
  • 显示数据之间是如何相互关联的(这有助于执行业务逻辑和规则)
  • 如果使用正确,可以帮助提高从表中提取数据的效率。

我认为 一件小事在某种程度上必须负责确保有效的关系。

例如,Ruby on Rails不使用外键,但它验证所有关系本身。如果您只是从 RubyonRails 应用程序访问数据库,那么这样做是可以的。

但是,如果您有其他正在写入数据库的客户端,那么如果没有外键,它们需要实现自己的验证。然后您有两个验证代码的副本,它们很可能是不同的,任何程序员都应该能够判断这是一个重大错误。

在这一点上,外键确实是必要的,因为它们允许您再次将责任移动到单个点上。

假设一个程序员实际上已经在以正确的方式做这件事

在我看来,做出这样的假设是一个非常糟糕的主意; 一般来说,软件存在明显的错误。

这才是重点,真的。开发人员无法正确处理问题,因此确保数据库不会被错误数据填充是一件好事。

尽管在理想情况下,自然连接将使用关系(即 FK 约束)而不是匹配列名。这将使 FK 更加有用。

就我个人而言,我更喜欢外键,因为它正式化了表之间的关系。我知道你的问题预先假定程序员不会引入违反参照完整性的数据,但是我已经看到太多违反数据参照完整性的例子了,尽管是出于好意!

前外键约束(又名声明性参照完整性或 DRI)花费了大量时间使用触发器来实现这些关系。我们可以通过声明性约束将关系形式化,这一点非常强大。

@ John-其他数据库可能会自动为外键创建索引,但 SQLServer 不会。在 SQLServer 中,外键关系只是约束。您必须单独定义外键上的索引(这可能有好处)

编辑: 我想补充一点,IMO,使用外键支持 ON DELETE 或 ON UPDATE CASCADE 并不一定是一件好事。在实践中,我发现应该根据数据的关系仔细考虑级联删除——例如,您是否有一个自然的父子关系,这可能是可以的,或者相关的表是一组查找值。使用级联更新意味着允许修改一个表的主键。在这种情况下,我有一个普遍的哲学上的不同意见,即表的主键不应该改变。键应该是固有的常量。

是的。

  1. 他们让你保持诚实
  2. 他们让新开发者保持诚实
  3. 你可以做 ON DELETE CASCADE
  4. 它们可以帮助您生成能够自我解释表之间链接的漂亮图表

我们目前不使用外键,而且大多数情况下我们并不后悔。

也就是说,在不久的将来,我们可能会更多地使用它们,原因有以下几点,两者的原因相似:

  1. 如果正确地使用了外键关系,那么生成数据库的关系图就容易得多。

  2. 工具支持。如果有适当的外键关系,那么使用可用于 从 LINQ 到 SQLVisualStudio2008构建数据模型要容易得多。

因此,我想我的观点是,我们已经发现,如果我们正在做大量的手动 SQL 工作(构造查询,运行查询,等等)外键不一定是必不可少的。不过,一旦你开始使用工具,它们就会变得非常有用。

它们不是严格必要的,就像安全带不是严格必要的一样。但他们真的可以让你免于做一些愚蠢的事情,搞乱你的数据库。

调试 FK 约束错误要比重新构造破坏应用程序的 delete 好得多。

关于外键约束(以及一般的约束) ,最好的事情是在编写查询时可以依赖它们。如果您不能依赖于保持“ true”的数据模型,那么许多查询可能会变得更加复杂。

在代码中,我们通常只是在某个地方抛出一个异常-但是在 SQL中,我们通常只是得到“错误”的答案。

理论上,SQL Server可以使用约束作为查询计划的一部分——但是除了分区的检查约束之外,我不能说我曾经亲眼目睹过这种情况。

没有 FK 约束的数据库模式就像没有安全带的驾驶。

总有一天,你会后悔的。不要在设计基本原理和数据完整性上花费那么少的额外时间,这肯定会让以后的工作更加头疼。

您会接受应用程序中如此草率的代码吗?直接访问成员对象并直接修改数据结构的。

你认为为什么现代语言中的 甚至无法接受甚至无法接受会变得这么难呢?

我是从成本/收益的角度来考虑的... ... 在 MySQL中,增加一个约束是 DDL的一个附加行。只是几个关键词和几秒钟的思考。在我看来,这是唯一的“代价”..。

工具喜欢外国钥匙。外键可以防止可能不会影响业务逻辑或功能的错误数据(即孤立的行) ,因此不会引起注意,并会产生错误数据。它还可以防止不熟悉模式的开发人员在没有意识到缺少关系的情况下实现整个工作块。也许在当前应用程序的范围内,一切都很好,但是如果你错过了一些东西,有一天又添加了一些意想不到的东西(想想花哨的报告) ,你可能就不得不手动清理自模式开始以来不断积累的坏数据,而无需进行数据库强制检查。

当你把事情整理到一起的时候,把你脑子里已经有的东西整理出来所需要的一点点时间,可以让你或者其他人在几个月甚至几年之后免于悲伤。

问题是:

外国人还有其他用途吗 钥匙? 我是不是漏掉了什么?

有点过头了。插入注释、缩进或变量命名来代替“外键”... ... 如果你已经完全理解了所讨论的内容,那么对你来说“没用”。

外键从来没有明确(FOREIGN KEY REFERENCES 表(列))声明在项目(商业应用程序和社交网站) ,我的工作。

但是总是有一种命名列的约定,这些列是外键。

这就像使用 数据库规范化一样——你必须知道你在做什么,这样做的后果是什么(主要是性能)。

我知道外键的优点(数据完整性、外键列的索引、了解数据库模式的工具) ,但我也害怕使用外键作为一般规则。

此外,各种数据库引擎可以以不同的方式为外键提供服务,这可能导致迁移过程中出现细微的错误。

使用 ON DELETE CASCADE 删除已删除客户端的所有订单和发票是外观漂亮但设计错误的数据库模式的完美例子。

没有外键有什么好处吗?除非你使用一个蹩脚的数据库,FK 并不难设置。那你为什么要避开他们呢?有一个变数命名原则说一列引用另一列是一回事,知道数据库实际上正在为你验证这种关系又是另一回事。

是的。ON DELETE [ RESTRICT | CASCADE ]防止开发人员搁浅数据,保持数据清洁。我最近加入了一个 Rails 开发人员团队,他们不关注数据库约束,比如外键。

幸运的是,我发现了这些: http://www.redhillonrails.org/foreign_key_associations.html—— RedHill on Ruby on Rails 插件使用 约定优于配置样式生成外键。使用 Product _ id进行迁移将在 产品表中创建到 身份证的外键。

查看 红山中的其他优秀插件,包括事务中包装的迁移。

外键允许以前从未见过您的数据库的人确定表之间的关系。

现在一切可能都很好,但是想想当你的程序员离开并且必须由其他人接管时会发生什么。

外键将允许他们理解数据库结构,而无需在数千行代码中进行拖网。

我想你说的是 由数据库强制的外键约束。您可能已经在使用外键,只是还没有告诉数据库。

假设一个程序员正在做 那就用正确的方式 我们真的需要 外国钥匙?

理论上来说,没有。然而,从来没有一个软件是没有缺陷的。

应用程序代码中的 bug 通常没有那么危险——您识别出 bug 并修复它,然后应用程序再次平稳运行。但是如果一个错误允许破坏的数据进入数据库,那么您就会被它困住!从数据库中损坏的数据恢复是非常困难的。

考虑 雾虫中的一个微妙的错误是否允许在数据库中写入损坏的外键。修复 bug 并在 bug 修复版本中将修复程序快速推送给客户可能很容易。但是,应该如何修复数十个数据库中的损坏数据?没错代码现在可能突然中断,因为关于外键完整性的假设不再成立。

在 Web 应用程序中,通常只有一个程序与数据库对话,因此只有一个地方存在可能破坏数据的 bug。在企业应用程序中,可能有几个独立的应用程序与同一个数据库对话(更不用说直接使用数据库 shell 的人员)。没有办法确保所有的应用程序都遵循相同的假设而没有 bug,永远都是这样。

如果约束是在数据库中编码的,那么最糟糕的错误就是向用户显示一条关于某些 SQL约束未得到满足的丑陋错误消息。这是 很多优于让破坏的数据进入您的企业数据库,它反过来将破坏您的所有应用程序或只是导致各种错误或误导的输出。

对了,外键约束还可以提高性能,因为它们是默认索引的。我想不出 没有使用外键约束的任何理由。

它们非常重要,因为您的应用程序不是在数据库中操作数据的唯一方式。你的应用程序可以诚实地处理参照完整性,但只需要一个有权限的笨蛋出现,在数据库级别发出插入、删除或更新命令,你的应用程序参照完整性执行就会被绕过。把 FK 约束放在数据库级别意味着,除非这个笨蛋选择在发出命令之前禁用 FK 约束,否则 FK 约束将导致一个错误的插入/更新/删除语句失败,并出现参照完整性冲突。

据我所知,外键用于帮助程序员以正确的方式操作数据。

当程序员 失败这样做时,FK 允许 DBA 保护数据完整性免于用户的笨拙,有时还可以保护用户免于程序员的笨拙。

假设一个程序员实际上已经在以正确的方式做这件事,那么我们真的需要外键的概念吗?

程序员是易犯错误的凡人。 FK 是 陈述性的,这使得他们更难搞砸。

外国钥匙还有其他用途吗? 我是不是漏掉了什么?

尽管这不是创建 FK 的原因,但是 FK 为图表工具和查询构建器提供了强有力的可靠提示。这会传递给最终用户,他们迫切需要强有力的可靠提示。

FK 非常重要,应该始终存在于您的模式 除非你是易趣中。

熵减少: 减少数据库中出现混沌场景的可能性。 我们有一个艰难的时期,因为它正在考虑所有的可能性,所以,在我看来,熵减少是维护任何系统的关键。

例如,当我们假设: 每个订单都有一个客户,这个假设应该由 什么的执行。在数据库中,“ something”是外键。

我认为这值得在开发速度上做出权衡。当然,关闭它们可以更快地进行编码,这可能就是为什么有些人不使用它们的原因。就个人而言,我已经杀死了一些小时与 冬眠和一些外国关键约束,当我执行一些操作生气。但是,我知道问题是什么,所以这不是什么大问题。我正在使用正常的工具,有资源可以帮助我解决这个问题,甚至可能有人来帮助我!

另一种方法是允许一个 bug 潜入系统(如果给予足够的时间,它就会潜入) ,在这种情况下没有设置外键,并且您的数据变得不一致。然后,你得到一个不寻常的错误报告,调查和“哦”。数据库完蛋了。要多久才能修好?

如果计划生成数据访问代码,即实体框架或任何其他 ORM,则完全丧失了生成没有外键的层次模型的能力