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

时间:2008-08-20 20:18:09

标签: database oracle foreign-keys

据我所知,外键(FK)用于帮助程序员以正确的方式操作数据。假设程序员实际上已经以正确的方式执行此操作,那么我们真的需要外键的概念吗?

外键还有其他用途吗?我在这里错过了什么吗?

24 个答案:

答案 0 :(得分:99)

外键有助于在数据级别强制实施参照完整性。它们还可以提高性能,因为它们通常默认为索引编制。

答案 1 :(得分:57)

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

答案 2 :(得分:43)

我无法想象没有外键设计数据库。没有它们,最终你肯定会犯错误并破坏数据的完整性。

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

我很确定FogBugz在数据库中没有外键约束。我很想知道Fog Creek Software团队如何构建他们的代码以保证他们永远不会引入不一致。

答案 3 :(得分:39)

没有FK约束的数据库架构就像没有安全带的驾驶一样。

有一天,你会后悔的。不要在设计基础和数据完整性上花费那么多的额外时间,这是确保后期头痛的可靠方法。

您是否接受应用程序中那些草率的代码?直接访问成员对象并直接修改数据结构。

为什么你认为在现代语言中这已经变得很难而且甚至是不可接受的

答案 4 :(得分:21)

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

答案 5 :(得分:13)

就个人而言,我赞成外键,因为它正式化了表之间的关系。我意识到你的问题预先假定程序员没有引入会违反参照完整性的数据,但是我已经看到了太多违反数据参照完整性的情况,尽管有最好的意图!

使用触发器实现这些关系花费了大量时间的外部外键约束(也称为声明性引用完整性或DRI)。我们可以通过声明性约束来形式化关系的事实是非常强大的。

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

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

答案 6 :(得分:12)

  

假设程序员实际上已经以正确的方式执行此操作

在我看来,做出这样的假设是一个非常糟糕的主意;通常情况下,软件是非常错误的。

这就是重点,真的。开发人员无法做到正确,因此确保数据库不能填充不良数据是一件好事。

虽然在理想的世界中,自然连接会使用关系(即FK约束)而不是匹配列名。这将使FK更加有用。

答案 7 :(得分:9)

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

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

答案 8 :(得分:8)

没有外键有没有好处?除非您使用的是蹩脚的数据库,否则FK并不难设置。那你为什么要有避免它们的政策呢?如果有一个命名约定说明一个列引用了另一个,那么另一个就是知道数据库实际上正在为你验证这种关系。

答案 9 :(得分:8)

我想你在谈论数据库强制执行的外键约束。你可能已经在使用外键了,你还没有告诉数据库它。

  

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

理论上,没有。但是,从来没有一个没有错误的软件。

应用程序代码中的错误通常不那么危险 - 您确定错误并修复它,然后应用程序再次顺利运行。但如果一个错误允许破解数据进入数据库,那么你就会陷入困境!从数据库中的损坏数据中恢复非常困难。

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

在Web应用程序中,您通常只有一个程序与数据库通信,因此只有一个地方可以破坏数据。在企业应用程序中,可能有几个独立的应用程序与同一个数据库通信(更不用说直接使用数据库shell的人)。无法确定所有应用程序是否始终如一地遵循相同的假设而不会出现错误。

如果在数据库中对约束进行编码,则错误可能发生的最坏情况是向用户显示关于某些SQL约束不满足的丑陋错误消息。这很多优先允许将数据压缩到您的企业数据库中,反过来它会破坏您的所有应用程序,或者只会导致各种错误或误导性输出。

哦,外键约束也可以提高性能,因为它们默认是索引的。我想不出使用外键约束的任何原因。

答案 10 :(得分:7)

FK非常重要,应始终存在于您的架构中unless you are eBay

答案 11 :(得分:6)

我认为某些事情在某些时候必须负责确保有效的关系。

例如,Ruby on Rails不使用外键,但它会验证所有关系本身。如果您只从Ruby on Rails应用程序访问您的数据库,这很好。

但是,如果您有其他正在写入数据库的客户端,那么在没有外键的情况下,他们需要实现自己的验证。然后,您有两个验证代码的副本,这些副本很可能是不同的,任何程序员应该能够告诉他们这是一个主要的罪过。

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

答案 12 :(得分:5)

  

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

当程序员失败时,FK允许DBA保护数据完整性免受用户笨拙的影响,有时可以防止程序员摸索。

  

假设程序员实际上已经以正确的方式执行此操作,那么我们真的需要外键的概念吗?

程序员是致命的,容易犯错。 FK是声明性的,这使得它们更难搞砸。

  

外键还有其他用途吗?我在这里错过了什么吗?

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

答案 13 :(得分:5)

外键允许之前没有看过您数据库的人确定表之间的关系。

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

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

答案 14 :(得分:4)

它们并非严格必要,因为安全带不是绝对必要的。但它们确实可以帮助你避免做一些弄乱数据库的愚蠢行为。

调试FK约束错误要比重建破坏应用程序的删除要好得多。

答案 15 :(得分:4)

它们很重要,因为您的应用程序不是数据库中数据操作的唯一方式。您的应用程序可以按照自己的意愿诚实地处理引用完整性,但只需要一个具有正确权限的bozo,并在数据库级别发出插入,删除或更新命令,并绕过所有应用程序引用完整性实施。将FK约束置于数据库级别意味着,除非在发出命令之前选择禁用FK约束,否则FK约束将导致错误的插入/更新/删除语句失败并引发参照完整性。

答案 16 :(得分:3)

我从成本/收益方面考虑......在MySQL中,添加约束是DDL的一个附加行。这只是一些关键词和几秒钟的思考。这是我认为唯一的“成本”......

工具喜欢外键。外键可防止可能不会影响业务逻辑或功能的错误数据(即孤立行),从而不会被注意到并构建。它还可以防止不熟悉架构的开发人员实现整个工作块,而不会发现他们错过了关系。也许在您当前应用程序的范围内一切都很好,但是如果您错过了某些东西,并且有一天会添加一些意想不到的东西(想想花哨的报告),那么您可能需要手动清理自开始以来一直在积累的错误数据。没有数据库强制检查的模式。

当你把东西放在一起时,把你脑子里已经存在的东西编成代码所花费的时间很少,可以在未来几个月或几年内为你或其他人带来一些悲伤。

问题:

  

外国还有其他用途吗?   钥匙?我在这里错过了什么吗?

有点装。插入注释,缩进或变量命名代替“外键”......如果你已经完全理解了有问题的东西,那对你来说是“没用”。

答案 17 :(得分:2)

熵减少。减少数据库中出现混乱情况的可能性。 我们很难考虑所有的可能性,因此,在我看来,减少熵是维护任何系统的关键。

当我们做出一个假设时,例如:每个订单都有一个客户,该假设应由某事强制执行。在“某事物”是外键的数据库中。

我认为这值得在开发速度上进行权衡。当然,你可以更快地编写代码,这可能是有些人不使用它们的原因。就个人而言,我已经用NHibernate杀死了几个小时,并且当我执行某些操作时,一些外键约束会生气。但是,我知道问题是什么,所以它不是一个问题。我正在使用普通工具,有资源可以帮助我解决这个问题,甚至可能有人帮忙!

另一种方法是允许一个bug进入系统(并给予足够的时间,它会),其中没有设置外键并且你的数据变得不一致。然后,你得到一个不寻常的错误报告,调查和“OH”。数据库搞砸了。现在要修复需要多长时间?

答案 18 :(得分:1)

在我工作的项目(业务应用程序和社交网站)中声明的外键从未明确(FOREIGN KEY REFERENCES表(列))。

但总是有一种命名列的惯例是外键。

就像database normalization一样 - 你必须知道你在做什么以及结果是什么(主要是表现)。

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

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

使用ON DELETE CASCADE删除已删除客户端的所有订单和发票是一个很好看但设计错误的数据库架构的完美示例。

答案 19 :(得分:1)

您可以将外键视为约束,

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

答案 20 :(得分:1)

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

在代码中,我们通常会在某处抛出异常 - 但在SQL中,我们通常会得到“错误”的答案。

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

答案 21 :(得分:1)

我们目前不使用外键。在大多数情况下,我们不会后悔。

那就是说 - 我们很可能在不久的将来开始使用它们有几个原因,原因有两个:

  1. 关系绘图。如果正确使用外键关系,则生成数据库图表要容易得多。

  2. 工具支持。如果有适当的外键关系,使用Visual Studio 2008构建数据模型要容易得多LINQ to SQL

  3. 所以我想我的观点是,我们发现如果我们做了大量的手工SQL工作(构造查询,运行查询,blahblahblah),外键不一定是必不可少的。但是,一旦开始使用工具,它们就会变得更有用。

答案 22 :(得分:0)

是。 ON DELETE [RESTRICT | CASCADE]使开发人员不会搁置数据,保持数据清洁。我最近加入了一个Rails开发团队,他们没有关注外键等数据库限制。

幸运的是,我发现了这些:http://www.redhillonrails.org/foreign_key_associations.html - Ruby on Rails插件上的RedHill使用convention over configuration样式生成外键。使用 product_id 进行迁移将为 products 表中的 id 创建外键。

查看RedHill上的其他优秀插件,包括交易中包含的迁移。

答案 23 :(得分:0)

如果您打算生成数据访问代码(例如Entity Framework或任何其他ORM),则完全失去了生成没有外键的层次模型的能力