假设我们有一个用户表:
+---------+----------+------------+------------+-- --------------+
|姓氏 |姓名 |邮编 |出生日期 |电子邮件 |
+---------+----------+------------+------------+-- --------------+
|琼斯 |约翰 | 60612-0344 | 1970-02-14 | john@jones.com |
|琼斯 |简 | 60612-0344 | 1971-05-26 | jane@jones.com |
|史密斯 |萨拉 | 19002-0052 | 1982-06-21 | sara@smith.com |
+---------+----------+------------+------------+-- --------------+
因为我们的应用程序要求每个用户都有自己不同的电子邮件地址,所以我们可以通过Email 列中的值来唯一标识表中的记录:它在表中形成了一个键。这样的键(在单个列上定义)被称为简单。
在某些情况下,可能知道没有两个用户可以有相同的姓名、出生日期和邮政编码:那么另一个可能的键是(Surname, Forename, ZIP, DOB) 的组合。这样的键(定义在多列上)被称为复合。
由于每条记录的键(根据定义)必须是唯一的,因此可以通过在相关列上定义 UNIQUE 索引来告诉 MySQL 强制执行此类唯一性约束(表的 PRIMARY KEY 是 @987654326 的一种特殊类型@index):尝试创建(或更新)与现有记录具有相同键的记录将失败。
现在假设有一张订单表:
+--------------+------------+---------+----------+
|订单号 |状态 |总计 |客户 |
+--------------+------------+---------+----------+
| 12345 |已完成 | 1234.99 | ? |
| 12346 |待定 | 345.00 | ? |
| 12347 |取消 | 9876.50 | ? |
+--------------+------------+---------+----------+
我们希望将订单与用户表中的相关记录相关联。但是怎么做呢?我们在Customer 列中添加了什么?
显然我们希望在 users 表中标识一条唯一记录,因此我们需要使用其中的一个键(例如上面第一个示例中的 Email)。以这种方式使用一个表的键从另一个表中引用其记录在关系数据库中非常普遍:在这种情况下,我们将引用列称为 外键(因为它将键保存在外部表)。
如果我们使用复合键作为参考,我们将有一个复合外键。在上面的第二个示例中,我们的订单表可能有列 Customer_Surname、Customer_Forename、Customer_ZIP 和 Customer_DOB,它们将一起形成用户表的外键(在这种情况下,我不推荐这样的架构)。
MySQL 不仅可以强制执行foreign key constraints(确保被引用的记录存在于外部表中),而且如果被引用的记录本身被更新或删除,也可以自动更新或删除引用(订单)表。例如,如果 John 从 users 表中删除,他的所有订单都可以自动从 orders 表中清除(同样,在这种情况下可能不是人们想要的);或者如果他的电子邮件地址发生了变化,Customer 列可以自动更新。