题
据我所知,外键(FK)用于帮助程序员以正确的方式操作数据。假设程序员实际上已经以正确的方式这样做了,那么我们真的需要外键的概念吗?
外键还有其他用途吗?我在这里错过了什么吗?
解决方案
外键有助于在数据级别强制执行引用完整性。它们还可以提高性能,因为它们通常是默认索引的。
其他提示
外键还可以帮助程序员使用以下内容编写更少的代码 ON DELETE CASCADE
. 。这意味着,如果您有一个表包含用户,另一个表包含订单或其他内容,那么删除用户可能会自动删除指向该用户的所有订单。
没有 FK 约束的数据库模式就像开车不系安全带一样。
有一天,你会后悔的。不花一点额外的时间在设计基础和数据完整性上肯定会导致以后的麻烦。
您会接受应用程序中如此草率的代码吗?直接访问成员对象并直接修改数据结构。
为什么你认为这变得很困难并且 甚至无法接受 在现代语言中?
是的。
- 他们让你保持诚实
- 他们让新开发者保持诚实
- 你可以做
ON DELETE CASCADE
- 它们可以帮助您生成漂亮的图表,自我解释表格之间的链接
就我个人而言,我赞成外键,因为它使表之间的关系形式化。我意识到你的问题预设了程序员没有引入会违反引用完整性的数据,但我已经看到太多违反数据引用完整性的实例,尽管有最好的意图!
前外键约束(也称为声明性引用完整性或 DRI)需要花费大量时间使用触发器来实现这些关系。我们可以通过声明性约束来形式化这种关系,这一事实非常强大。
@John - 其他数据库可能会自动为外键创建索引,但 SQL Server 不会。在 SQL Server 中,外键关系只是约束。您必须单独在外键上定义索引(这可能会有好处。)
编辑:我想补充一点,在我看来,使用外键来支持 ON DELETE 或 ON UPDATE CASCADE 不一定是一件好事。在实践中,我发现删除时的级联应该根据数据的关系仔细考虑——例如您是否有一个自然的父子关系,这可能没问题,或者相关表是一组查找值。使用级联更新意味着您允许修改一个表的主键。在这种情况下,我有一个普遍的哲学分歧,即表的主键不应更改。密钥本质上应该是恒定的。
假设程序员实际上已经以正确的方式这样做了
在我看来,做出这样的假设是一个极其糟糕的主意。一般来说,软件存在明显的错误。
这就是重点,真的。开发人员无法把事情做好,因此确保数据库不会被错误数据填充是一件好事。
尽管在理想的世界中,自然连接将使用关系(即FK 约束)而不是匹配列名。这将使 FK 更加有用。
如果没有外键,您如何判断不同表中的两条记录相关?
我认为您指的是参照完整性,即在没有现有父记录等的情况下不允许创建子记录。这些通常被称为外键约束 - 但首先不要与外键的存在相混淆。
没有外键有好处吗?除非您使用的是蹩脚的数据库,否则 FK 的设置并不难。那么为什么要制定避免它们的政策呢?有一个命名约定表明一列引用另一列是一回事,而知道数据库实际上正在为您验证这种关系则是另一回事。
我想你正在谈论 数据库强制执行的外键约束. 。您可能已经在使用外键,只是没有告诉数据库。
假设程序员实际上已经以正确的方式执行此操作了,那么我们真的需要外国钥匙的概念吗?
理论上来说,不会。然而,从来没有一款软件没有错误。
应用程序代码中的错误通常并不那么危险 - 您识别错误并修复它,然后应用程序再次顺利运行。但是,如果错误允许损坏的数据进入数据库,那么您就陷入困境了!从数据库中损坏的数据中恢复非常困难。
考虑一下是否存在细微的错误 雾虫 允许在数据库中写入损坏的外键。修复错误并在错误修复版本中快速将修复推送给客户可能很容易。然而,如何修复数十个数据库中的损坏数据呢? 正确的 代码现在可能会突然崩溃,因为关于外键完整性的假设不再成立。
在 Web 应用程序中,通常只有一个程序与数据库通信,因此只有一处错误会损坏数据。在企业应用程序中,可能有多个独立的应用程序与同一个数据库通信(更不用说直接使用数据库 shell 的人员)。无法确保所有应用程序始终遵循相同的假设,没有错误。
如果约束被编码在数据库中,那么错误可能发生的最糟糕的情况就是向用户显示关于某些内容的丑陋错误消息。 SQL 不满足约束。这是 很多 最好不要让损坏的数据进入您的企业数据库,否则它会破坏您的所有应用程序或导致各种错误或误导性的输出。
哦,外键约束也提高了性能,因为它们默认被索引。我想不出任何理由 不是 使用外键约束。
FK 非常重要,应该始终存在于您的架构中, 除非你是易趣.
我认为 一些单一的事情 在某些时候必须负责确保有效的关系。
例如, 红宝石 on Rails 不使用外键,但它本身验证所有关系。如果您只从 Ruby on Rails 应用程序访问数据库,那么这很好。
但是,如果您有其他客户端正在写入数据库,那么在没有外键的情况下,它们需要实现自己的验证。然后,您将拥有两个很可能不同的验证代码副本,任何程序员都应该能够看出这是一个重大罪过。
在这一点上,外键确实是必要的,因为它们允许您再次将责任转移到一个点。
外键允许以前没有见过您的数据库的人确定表之间的关系。
现在一切可能都很好,但想想当你的程序员离开并且其他人必须接管时会发生什么。
外键将使他们能够理解数据库结构,而无需浏览数千行代码。
据我所知,外键用于帮助程序员以正确的方式操作数据。
FK 允许 DBA 在程序员编写数据时保护数据完整性,避免用户的误操作 失败 这样做,有时是为了防止程序员的失误。
假设程序员实际上已经以正确的方式这样做了,那么我们真的需要外键的概念吗?
程序员都是凡人,容易犯错。FK 是 陈述性的 这使得他们更难搞砸。
外键还有其他用途吗?我在这里错过了什么吗?
尽管这不是创建它们的原因,但 FK 为图表工具和查询生成器提供了强大可靠的提示。这会传递给最终用户,他们迫切需要强大可靠的提示。
它们并不是绝对必要的,就像安全带不是绝对必要的一样。但它们确实可以让您避免做一些愚蠢的事情来搞乱您的数据库。
调试 FK 约束错误比重建破坏应用程序的删除要好得多。
它们很重要,因为您的应用程序并不是在数据库中操作数据的唯一方式。您的应用程序可以按照自己的意愿诚实地处理引用完整性,但所需要的只是一个具有正确权限的笨蛋在数据库级别发出插入、删除或更新命令,并且所有应用程序引用完整性强制都会被绕过。将 FK 约束放入数据库级别意味着,除非这个笨蛋在发出命令之前选择禁用 FK 约束,否则 FK 约束将导致错误的插入/更新/删除语句失败,并导致引用完整性违规。
我从成本/收益的角度来考虑...在 MySQL, ,添加约束是一个附加行 数据定义语言. 。这只是几个关键词和几秒钟的思考。这是我认为唯一的“成本”......
工具喜欢外键。外键可以防止不良数据(即孤立行),这些数据可能不会影响业务逻辑或功能,因此不会被注意到并累积。它还可以防止不熟悉模式的开发人员在没有意识到他们缺少关系的情况下实现整个工作块。也许在您当前的应用程序范围内一切都很好,但是如果您错过了某些内容并且有一天添加了一些意想不到的内容(想想花哨的报告),您可能会遇到这样的情况:您必须手动清理从一开始就积累的不良数据没有数据库强制检查的模式。
当你把事情放在一起时,花一点时间来整理你头脑中已经存在的东西,可以为你或其他人在未来几个月或几年的悲伤中节省下来。
问题:
外国钥匙还有其他用途吗?我在这里错过了什么吗?
它有点负载。插入注释、缩进或变量命名来代替“外键”...如果你已经完全理解了所讨论的问题,那么它对你来说“没有用”。
熵减少。减少数据库中出现混乱情况的可能性。我们遇到了困难,因为它要考虑所有的可能性,所以在我看来,熵减少是维护任何系统的关键。
例如,当我们做出假设时:每个订单都有一个客户,该假设应由 某物. 。在数据库中,“某物”是外键。
我认为这是值得在开发速度上进行权衡的。当然,关闭它们你可以更快地编码,这可能就是为什么有些人不使用它们的原因。就我个人而言,我已经消磨了好几个小时了 NHibernate 以及当我执行某些操作时一些外键约束会生气。然而,我知道问题是什么,所以这不是问题。我正在使用普通工具,并且有资源可以帮助我解决这个问题,甚至可能有人可以提供帮助!
另一种方法是允许错误潜入系统(只要有足够的时间,它就会),其中未设置外键并且数据变得不一致。然后,您会收到一份不寻常的错误报告,进行调查并“哦”。数据库被搞砸了。现在需要多长时间才能修复?
您可以将外键视为约束,
- 帮助维护数据完整性
- 显示数据如何相互关联(这有助于执行业务逻辑和规则)
- 如果使用正确,可以帮助提高从表中获取数据的效率。
我们目前不使用外键。在大多数情况下,我们并不后悔。
也就是说,出于以下几个原因,我们可能会在不久的将来开始更多地使用它们,这两个原因都是相似的:
图表化。如果正确使用外键关系,则生成数据库图表会容易得多。
工具支持。使用构建数据模型要容易得多 视觉工作室2008 可以用于 LINQ 到 SQL 是否存在适当的外键关系。
所以我想我的观点是,我们发现,如果我们进行大量手动 SQL 工作(构造查询、运行查询等),那么外键不一定是必需的。然而,一旦你开始使用工具,它们就会变得更加有用。
我所从事的项目(业务应用程序和社交网站)中从未明确声明过外键(FOREIGN KEY REFERENCES 表(列))。
但总是存在一种命名外键列的约定。
就像与 数据库规范化 ——你必须知道你在做什么以及这样做的后果是什么(主要是表现)。
我知道外键的优点(数据完整性、外键列索引、了解数据库模式的工具),但我也害怕使用外键作为一般规则。
此外,各种数据库引擎可能以不同的方式提供外键,这可能会导致迁移过程中出现微妙的错误。
使用 ON DELETE CASCADE 删除已删除客户的所有订单和发票是外观漂亮但设计错误的数据库模式的完美示例。
是的。ON DELETE [RESTRICT|CASCADE] 可防止开发人员搁浅数据,保持数据干净。我最近加入了一个 Rails 开发人员团队,他们并不关注外键等数据库约束。
幸运的是,我发现了这些: http://www.redhillonrails.org/foreign_key_associations.html -- RedHill on Ruby on Rails 插件使用以下命令生成外键 约定优于配置 风格。迁移与 产品编号 将创建一个外键 ID 在里面 产品 桌子。
查看其他很棒的插件: 红丘, ,包括包含在事务中的迁移。