在MySQL中使用外键还是不使用?

在MySQL中使用外键还是不使用?,mysql,foreign-keys,Mysql,Foreign Keys,我已经用MySQL DBs编写代码好几年了,我从来没有使用过外键。现在,我了解到外键就像一个表上的ID,与另一个表的主键对应。我在我的站点上有一个用户表,可能还有大约10个其他表,它们都与我的用户表的主键对应——但是它们没有设置为外键 如果其他10个表没有外键,我会错过什么?我的意思是,据我所知,它们基本上是一个外键,除非它们没有在数据库中保存/分配给它们的值 还有其他我不知道的好处吗 我也意识到主键不能为空,但外键可以为空。在我的情况下,这永远不会是一个问题,因为我的用户表已经创建,并且当一个

我已经用MySQL DBs编写代码好几年了,我从来没有使用过外键。现在,我了解到外键就像一个表上的ID,与另一个表的主键对应。我在我的站点上有一个用户表,可能还有大约10个其他表,它们都与我的用户表的主键对应——但是它们没有设置为外键

如果其他10个表没有外键,我会错过什么?我的意思是,据我所知,它们基本上是一个外键,除非它们没有在数据库中保存/分配给它们的值

还有其他我不知道的好处吗


我也意识到主键不能为空,但外键可以为空。在我的情况下,这永远不会是一个问题,因为我的用户表已经创建,并且当一个新用户添加到我的用户表中时,我会将其相应的条目添加到其他10个表中。

您缺少的是强制引用完整性(即,如果您的其他表具有
用户id
27,则用户表中必须有id 27)以及自动级联更新和删除的功能(即,如果删除用户27,另一个表中的相应行也会自动删除,等等)


在我看来,这不值得。我完全能够拥有代码地址引用完整性,处理外键是维护的一大麻烦。

A
外键
有两个用途:

  • 它可以确保您的关系始终保持一致,但要付出一定的检查开销
  • 它(有争议地)简化了级联更新和删除
在大多数情况下,使用其他工具可以更有效地实现此功能。

使用外键可以

  • 可以确保仅将有效的用户id放入这些字段
  • 在删除时使用级联更容易避免
  • 不必在这些字段上手动定义索引(innodb)

在某些数据库中(不确定MySQL),一个
外键会自动索引,这可以很好地加速外键的连接和查询。此外,还有前面提到的级联删除、引用完整性等好处。

添加外键始终是一个好主意-至少我从未见过不使用外键的令人信服的理由

  • 强制引用完整性(如果存在子项,则无法删除父项,无法插入孤立项,或父项id无效的子项)
  • 用作索引
  • 使用外键,无论数据是如何访问的,无论是通过应用程序、自动化流程还是终端上没有咖啡因的人,规则都是统一执行的

在MySQL中定义外键基本上是一个别名,用于设置1)索引2)约束(实际的fkey),因此,是的,您可以从中获取索引。当前,当用户删除帐户时,我将代码从其他10多个表中删除,您是说这一切都可以自动化吗?我更好奇你提到的更新,那会是什么do@chaos:我相信您的代码在执行引用完整性方面总是完美无缺的,但是其他人访问同一数据库的代码呢?或者在查询工具中运行特殊查询?数据库强制RI的要点是,即使客户端不一致,它也是一致的。我在这里的答案中看到很多“你可以自己在代码中完成”,这是严重的误导。我无法统计在数月或数年的时间里,有多少数据库变成了一堆无效数据。毫无例外,如果在模式中正确实施引用完整性,它们中的每一个都会非常干净。外键不是可选的——它们是良好数据库设计的关键组成部分。然后,您假设在DB上总会有额外的层,用于DB已经具有的目的。我发现这是一种相当现代的方法,但仍然认为它非常糟糕。“JA:通常使用的层称为存储过程,而不是”代码> dB<代码>。外键的主要缺点是它们的逐行实现,这是一个性能杀手,如果您需要或多或少定期进行大规模更新。因此,您将为每个表创建类似于插入触发器之前的内容来强制执行约束?它真的更有效率吗?只是问,不是说不是。真奇怪。因为您可以制作一些类似于存储过程api的东西,用于插入/更新数据,但它是100%安全的吗?如果有人直接调用insert怎么办?@Jan:我创建了一个存储过程来处理表中的插入、更新和删除操作(实际上,我有一个脚本可以根据表的定义创建一个默认过程)。这些过程接受一个集合作为输入(除了MySQL之外的所有主要引擎都支持它),这肯定比一系列单独的插入更有效。直接调用
INSERT
是不可能的,因为它不是在表上授予的,而是在procs上执行的。性能优势只有在大规模更新时才明显,但是,我很久以前就开发了脚本,甚至在纯
OLTP
应用程序中也使用了这种方法。如果是这种情况,我同意你的看法+1并收回我的第一个不同意意见。感谢您将这一点讲清楚,从您的答案中可以看出这一点并不明显:)使用外键时,请用力缩放