外键在数据库devise中是否真的有必要?
据我所知,外键(FK)被用来帮助程序员以正确的方式处理数据。 假设一个程序员实际上已经以正确的方式来做这件事了,那么我们是否真的需要外键的概念呢?
有没有其他用途的外键? 我在这里错过了什么?
外键有助于在数据级强制执行参照完整性。 它们也可以提高性能,因为它们通常是默认索引的。
外键也可以帮助程序员使用ON DELETE CASCADE来编写更less的代码。 这意味着,如果您有一个包含用户的表,另一个包含订单或其他内容,则删除用户可能会自动删除指向该用户的所有订单。
我无法想象devise一个没有外键的数据库。 没有它们,最终你肯定会犯错误,并破坏数据的完整性。
严格来说,这不是必需的 ,但好处是巨大的。
我相当肯定, FogBugz在数据库中没有外键约束。 我想知道Fog Creek软件团队如何构build他们的代码来保证他们不会引入不一致的问题。
没有FK约束的数据库模式就像没有安全带的驾驶一样。
有一天,你会后悔的。 不要在devise基础和数据完整性上花费额外的时间,这是确保后来头痛的一个可靠的方法。
你会接受那个马虎的代码吗? 直接访问成员对象并直接修改数据结构。
你为什么认为在现代语言中这已经变得困难甚至不可接受了 ?
是。
- 他们让你诚实
- 他们让新开发人员诚实
- 你可以做
ON DELETE CASCADE
- 他们帮助你生成好的图表,自我解释表之间的联系
假设一个程序员实际上是以正确的方式来做这件事的
做出这样的假设在我看来似乎是一个非常糟糕的主意。 在一般的软件是惊人的错误。
这真的是重点。 开发人员不能把事情搞对,所以保证数据库不能填充不好的数据是件好事。
尽pipe在一个理想的世界中,自然连接会使用关系(即FK约束)而不是匹配列名。 这将使FKs更有用。
就个人而言,我赞成外键,因为它正式化了表格之间的关系。 我意识到你的问题的前提是程序员没有引入违反引用完整性的数据,但是尽pipe有最好的意图,但是我看到了太多违反数据引用完整性的实例!
使用触发器花费了大量时间来实现这些关系之前的外键约束(又名声明性参照完整性或DRI)。 我们可以通过声明性约束来forms化关系的事实是非常强大的。
@John – 其他数据库可能会自动为外键创build索引,但是SQL Server不会。 在SQL Server中,外键关系只是约束。 您必须单独在外键上定义您的索引(这可能会有好处)。
编辑:我想补充说,国际海事组织,使用外键支持ON DELETE或ON UPDATE CASCADE不一定是一件好事。 在实践中,我发现基于数据的关系,应该仔细考虑级联删除 – 例如,你有一个自然的父母孩子,这可能是好的,或者是相关表中的一组查找值。 使用级联更新意味着您允许修改一个表的主键。 在那种情况下,我有一个普遍的哲学上的分歧,那就是表格的主键不应该改变。 关键应该是固有的。
没有外键你怎么知道不同表格中的两条logging是相关的?
我认为你所指的是参照完整性,其中不允许在没有现有父logging的情况下创build子logging等。这些通常被称为外键约束 – 但是不应该将其与外键的存在相混淆第一个地方。
没有外键有没有好处? 除非你正在使用一个蹩脚的数据库,否则FKs不是很难设置。 那么为什么你会有一个避免他们的政策? 拥有一个列引用另一个列的命名约定是一回事,知道数据库实际上正在validation您的关系是另一回事。
我想你是在谈论由数据库强制执行的外键约束 。 你可能已经在使用外键了,你只是没有告诉数据库。
假设一个程序员实际上已经以正确的方式来做这件事了,那么我们是否真的需要外键的概念呢?
理论上,不。 但是,从来没有一个没有bug的软件。
应用程序代码中的错误通常不是那么危险的 – 您找出错误并修复错误,之后应用程序再次顺利运行。 但是,如果一个错误允许中断数据进入数据库,那么你坚持它! 从数据库中的损坏数据恢复是非常困难的。
考虑一下FogBugz中的一个微妙的错误是否允许在数据库中写入一个损坏的外键。 修复这个错误可能很容易,并且可以很快地将这个修补程序推送给修补程序版本中的客户。 但是,如何解决数十个数据库中的腐败数据呢? 正确的代码现在可能突然中断,因为关于外键完整性的假设不再成立。
在Web应用程序中,通常只有一个程序与数据库对话,所以只有一个地方可能会导致数据损坏。 在企业应用程序中,可能有多个独立的应用程序对同一个数据库(更不用说直接使用数据库shell的人员)进行对话。 没有办法确定所有的应用程序都遵循相同的假设,无时无刻都是错误的。
如果在数据库中对约束条件进行了编码,那么可能发生的最大错误是用户会看到关于某些SQL约束不满足的丑陋的错误消息。 这对于让您的企业数据库中断数据,这反过来将打破所有的应用程序,或者只是导致各种错误或误导输出,这是非常有利的。
呵呵,外键约束也提高了性能,因为它们是默认索引的。 我想不出有什么理由不使用外键约束。
FK非常重要,应该始终存在于您的架构中, 除非您是eBay 。
我认为在某个时候某件事情必须负责确保有效的关系。
例如, Ruby on Rails不使用外键,而是validation所有的关系本身。 如果你只从Ruby on Rails应用程序访问你的数据库,这没问题。
但是,如果您有其他正在写入数据库的客户机,则无需使用外键就可以实现自己的validation。 然后,您有两个最有可能不同的validation代码副本,程序员应该能够说出这是一个基本的罪过。
在这一点上,外键确实是必要的,因为它们允许你将责任重新转移到一个单一的点。
外键允许之前没有看过数据库的人来确定表之间的关系。
现在一切都好了,但是想想当你的程序员离开,别人必须接pipe时会发生什么。
外键将使他们能够理解数据库结构,而不用通过数千行代码进行拖网。
据我所知,外键用来帮助程序员以正确的方式处理数据。
FK允许DBA保护数据的完整性,避免程序员不能这样做,有时为了防止程序员摸不着头脑。
假设一个程序员实际上已经以正确的方式来做这件事了,那么我们是否真的需要外键的概念呢?
程序员是致命的和易错的。 FK是声明性的 ,这使得它们更难以搞砸。
有没有其他用途的外键? 我在这里错过了什么?
虽然这不是创build它们的原因,但FK为绘图工具和查询构build器提供了强大的可靠提示。 这被传递给最终用户,他们迫切需要强大的可靠提示。
他们并不是绝对必要的,安全带并不是绝对必要的。 但是,他们真的可以让你免于做一些愚蠢的事情来破坏你的数据库。
debuggingFK约束错误要比重构一个破坏应用程序的删除更好。
它们很重要,因为您的应用程序不是数据库中唯一可以操作的数据。 您的应用程序可以按照自己的意愿诚实地处理引用完整性,但只需要一个具有正确权限的权限,并在数据库级别发出插入,删除或更新命令,并且绕过所有应用程序参照完整性实施。 将FK约束放在数据库级别意味着,除非这个bozoselect在发出它们的命令之前禁用FK约束,否则FK约束将导致错误的插入/更新/删除语句在参照完整性违反的情况下失败。
我从成本/效益的angular度考虑它…在MySQL中 ,添加一个约束是DDL的一个额外的行。 这只是less数关键词和几秒钟的思考。 这是我认为唯一的“成本”…
工具喜欢外键。 外键防止可能不会影响业务逻辑或function的不良数据(也就是孤行),因此不被忽视和build立。 它还可以防止不熟悉模式的开发人员实现整个工作块,而不会意识到他们错过了一段关系。 也许在你当前应用程序的范围内,一切都很好,但是如果你错过了某些事情,而且有一天会有意想不到的事情发生,那么你可能会处于一个必须手动清理自成立以来积累的不良数据的地方没有数据库强制检查的模式。
当你把东西放在一起的时候,把头脑中已经存在的东西编码起来所花费的时间很less,这样可以为你或者其他人一个个悲伤数月或者数年。
问题是:
有没有其他用途的外键? 我在这里错过了什么?
这是一个有点装。 插入注释,缩进或variables命名代替“外键”…如果你已经完全理解了这个问题,那对你来说是“无用的”。
熵减less。 减less数据库中发生混沌情况的可能性。 我们很难考虑所有可能的情况,因此,我认为减less熵是维持任何系统的关键。
当我们假设一个例子:每个订单都有一个顾客,这个假设应该由某个东西来执行。 在“某些东西”是外键的数据库中。
我认为这是值得的发展速度的权衡。 当然,你可以更快地编写代码,这可能是为什么有些人不使用它们。 就我个人而言,我用NHibernate和一些外键约束已经杀了好几个小时,当我执行一些操作时会生气。 但是,我知道问题是什么,所以这不是一个问题。 我正在使用普通的工具,并有资源来帮助我解决这个问题,甚至可能有人帮忙!
另一种方法是允许一个错误进入系统(并给予足够的时间,它会),一个外键没有设置,你的数据变得不一致。 然后,你会得到一个不寻常的错误报告,调查和“哦”。 数据库被拧紧了。 现在需要多长时间才能解决?
您可以将外键视为一个约束,
- 帮助维护数据完整性
- 显示数据如何相互关联(这可以帮助执行业务逻辑和规则)
- 如果使用正确,可以帮助提高从表中提取数据的效率。
我们目前不使用外键。 而大多数情况下,我们并不后悔。
这就是说 – 由于几个原因,我们可能会在不久的将来开始使用它们,原因有二:
-
图表。 如果有正确使用的外键关系,那么生成一个数据库图就容易多了。
-
工具支持。 如果有适当的外键关系,使用Visual Studio 2008构build数据模型可以更容易地用于LINQ to SQL 。
所以我想我的观点是,我们发现如果我们正在做大量的手工SQL工作(构造查询,运行查询,blahblahblah)外键不一定是必要的。 一旦开始使用工具,它们变得更有用。
关于外键约束(和通常的约束)最好的事情是在编写查询时可以依赖它们。 如果你不能依赖数据模型中的“true”,很多查询会变得复杂得多。
在代码中,我们通常只会得到一个抛出的exception – 但在SQL中 ,我们通常只会得到“错误的”答案。
从理论上讲, SQL Server可以使用约束作为查询计划的一部分 – 但除了检查分区约束之外,我不能说我真的亲眼目睹了这一点。
在我工作的项目(业务应用程序和社交网站)中声明的外键从未明确(FOREIGN KEY REFERENCES表(列))。
但总是有一种命名为外键的列的约定。
这就像数据库正常化 – 你必须知道你在做什么,以及这是什么结果(主要是性能)。
我知道外键的优点(数据完整性,外键列索引,知道数据库模式的工具),但是我也害怕使用外键作为一般规则。
各种数据库引擎也可以以不同的方式提供外键,这可能会导致在迁移过程中出现微妙的错误。
使用ON DELETE CASCADE删除已删除客户端的所有订单和发票是一个很好的例子,但是devise错误,数据库模式错误。
是。 ON DELETE [RESTRICT | CASCADE]让开发人员避免数据搁浅,保持数据清洁。 我最近join了一个Rails开发人员团队,他们不专注于数据库的限制,比如外键。
幸运的是,我发现这些: http : //www.redhillonrails.org/foreign_key_associations.html – Ruby on Rails插件上的RedHill使用约定优于configuration样式生成外键。 使用product_id进行迁移将在产品表中为id创build一个外键。
查看RedHill中的其他优秀插件,包括交易中包装的迁移。