我将在这里大吃一惊,虽然我实际上不知道我的答案是否准确,所以如果您了解数据库工程的内部内容,请纠正我。但如果我是对的,我认为这会有所帮助。
外键及其关联的外键约束不是一回事,就像汽车发动机和曲轴不是一回事一样。发动机将汽油的爆炸转化为直线运动(活塞),曲轴将直线运动转化为转动运动,然后转动汽车的车轮。发动机和曲轴一起使汽车行驶。
同样,外键和外键约束不是一回事,但它们共同创造了“外键关系”的概念。
定义:
“外键”是外键索引的缩写。
“约束”是外键约束的缩写。
索引和约束共同构成“外键关系”。
外键关系要求子表中的值存在于其父表中,从而确保数据库中的数据完整性。
因为Key是Index的意思,所以我们不说“外键索引”。我们只说外键,但不说“索引”是造成很多混乱的原因。
创建外键(外键索引)会创建二叉搜索树(也称为字典,因为树用于查找值)。二叉搜索树(BST)然后存在于计算机内存中并占用物理磁盘空间,但允许从子表到父表的 O(log n) JOIN 访问时间(几乎立即)。
创建外键约束就是创建一个规则,它是一段代码,当您在外键列上处理(INSERT、SELECT 等)时会调用它。约束本质上是一个数据库触发器。约束就像电子邮件过滤器:在某个操作上调用的一段代码,例如 WHEN(新电子邮件)IF(来自:crzy@xgfrnd.com){SEND TO Trash Folder;}。
因此,外键“约束”将是一段被调用的代码(本质上是触发器),看起来像这样:当插入 child_column IF (NOT IN parent_table) DO NOT ALLOW INSERT。
然后你有你的级联和更新和删除规则(约束),以及它们的各种 if / then 条件和操作等......
因此,“外键”是将子表列值映射到父表列值的 BST 字典。外键的目的是速度(不是数据完整性,因为可以在没有索引的情况下实现数据完整性,尽管速度很慢)。
外键约束是一条规则:在 SQL 语句上触发的代码,并且该规则使用 BST 作为快速处理的字典,以避免遍历表,这最终可能会产生类似笛卡尔的行为。外键约束的目的是数据完整性。
我从来没有创建一个父表,其中引用的父列本身不是父表中的键。那么问题来了,外键索引(BST 字典)真的需要吗?约束是肯定需要的,以确保数据完整性,但外键索引(BST 字典)实际上不需要外键规则,因此,“键”和“索引”有两个不同的定义。“Index”是 BST 树,“Key”是规则(子值必须存在于父表中的想法)。然而,在 MySQL 中,需要外键索引,只是因为他们以这种方式对其进行了编程,但他们不必这样做。当父列本身没有索引时,拥有 BST 树会更快。我永远不会建议使引用的父列不是键(索引)。但是,如果有人确实使用没有 BST 的外键约束引用了非索引父列,那么 SQL 操作将逐渐变慢,并且您的应用程序最终可能会陷入困境。
混乱:形容词和动词。
当我们通俗地说“外键”时,我们通常指的是外键关系,而不是外键索引。但是Key这个词的意思是索引。所以这就是所有混乱的根源。即缺乏保留关键字定义标准。在 MySQL CREATE TABLE 语句中,FOREIGN KEY 表示索引(BST),而 CONSTRAINT 命名规则,因此,混淆来自我们说话时短语“外键”与定义的“外键”的差异在实际的 SQL 语句中。
在计算机代码中,“Foreign”是形容词,“Key”是名词,表示索引。
在口语中,“外键”是形容词,“索引”、“约束”、“关系”都是名词。当我们在办公室隔间相互交谈时,“外键”意味着数据完整性的“想法”(即规则,而不是索引)。
不幸的是,程序员总是在寻找简写的打字方式,这常常会引起混乱。计算机科学中的一切都是一种权衡,包括编码风格。
如果创建 MySQL 表的语法改为使用以下保留字,那么混淆就会消失: FOREIGN KEY CONSTRAINT fk1_rule_child_column
FOREIGN KEY INDEX ( fk_bst_child_to_parent_column
) REFERENCES parent_table
( parent_column
)
此外,由于 MySQL 总是同时创建索引和约束,因此 MySQL 创建者可以完全隐藏(抽象)外键关系的双重元素。或者,也许我应该说,他们可以将它们捆绑在一起,这样用户就不必考虑双重方面,而只需创建一个my_foreign_key
隐藏双重细节的“外键”。
尽管如此,MySQL 价格低廉、功能强大,而且非常棒。郑重声明,我的抱怨是零,我只对创作者表示感谢。就我而言,他们可以为所欲为。
顺便说一句,作为一种风格推荐,您应该始终将父列和子列命名相同,并且您的表名应该始终包含它们的外键关系。所以你的桌子
customers
products
attributes
orders
应该改为命名
customers
products
product_attributes
customer_product_orders
这样,您和您的继任者只需读取任何表名即可知道外键关系。如果这对您来说打字太多,那么
cust
prod
prod_attr
cust_prod_ord
话虽如此,我猜。我实际上不知道我的 BST 和规则解释是否正确,但我认为它是正确的,希望能解决这个令人困惑的问题。但如果你们这些数据库专家确认、修改、补充或否认我所写的内容,我将不胜感激,如果我弄错了,真正的答案是什么,所以我们最终可以解决这个多代人的谜团. 如果我完全关闭,并且需要删除此答案,那也很好。