2.3 主键、外键与数据关系


2.3 主键、外键与数据关系

本节摘要:主键唯一标识一行,外键把表关联起来。这两个概念是关系型数据库"关系"二字的来源。本节讲清它们的作用、怎么定义、以及一对一/一对多/多对多关系。

核心问题

阅读完本节,你应当能够:

  1. 说清主键的定义和作用
  2. 说清外键的定义和作用
  3. 区分一对一、一对多、多对多关系
  4. 理解外键约束的参照完整性

一、主键:唯一标识一行

主键(Primary Key)是一列(或几列)的组合,能唯一标识表里的每一行,且不能为 NULL。比如 Customers 表的 CustomerID——每个客户一个唯一 ID,靠它定位某一行。

主键的要求:

  • 唯一:每行的主键值不同
  • 非空:不能是 NULL
  • 尽量不变:主键值一般不修改
CREATE TABLE Customers ( CustomerID INT PRIMARY KEY, FirstName VARCHAR(50), ... );

主键可以是单列,也可以是多列组合(复合主键),比如订单明细表用 (OrderID, ProductID) 组合唯一标识一行。

二、外键:把表关联起来

外键(Foreign Key)是一列,它的值引用另一张表的主键,表示"这行属于那个对象"。比如 Orders 表的 CustomerID 引用 Customers 的 CustomerID——某条订单属于某个客户。

图 2-3 主外键关系图

图 2-3 主外键关系图

外键的作用是建立表间关系 + 保证参照完整性。参照完整性指:外键值必须在被引用表的主键里存在,不能引用一个不存在的对象。比如不能给一个不存在的客户 ID 插订单。

CREATE TABLE Orders ( OrderID INT PRIMARY KEY, CustomerID INT, Amount DECIMAL(10,2), FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID) );

三、三种关系基数

表之间的关系按"一端能对应几条"分三种:

一对多(最常见)

一个客户有多条订单,一条订单只属于一个客户。Customers 对 Orders 是一对多。这是最常见的,靠在"多"的一方加外键实现(Orders.CustomerID)。

一对一

一行只对应一行。比如用户表和用户详情表,分开存以减少主表宽度。靠在从表加唯一外键实现。

多对多

学生和课程:一个学生选多门课,一门课有多学生。关系型不能直接表达多对多,要用一张中间表(选课表)拆成两个一对多。

关系 例子 实现方式
一对多 客户-订单 多方加外键
一对一 用户-详情 从表加唯一外键
多对多 学生-课程 中间表拆成两个一对多

四、外键约束的代价

外键保证数据一致性,但有代价:插入/删除/更新要检查约束,性能略降;级联操作可能引发连锁。所以有些高并发系统不用外键约束,改在应用层保证一致性。入门阶段建议用外键,理解了再权衡。

⚠️ 常见坑:建了外键后删被引用的行报错(有子记录依赖)。要么先删子记录,要么用 ON DELETE CASCADE 级联删(慎用,会连锁删一堆)。

💡 关键直觉:主键管"唯一标识自己",外键管"和别人建立关系"。关系型数据库的"关系"就是靠外键织起来的网。

本章回顾

  • 主键:唯一标识一行,非空,可单列可复合。
  • 外键:引用另一表主键,建立关系 + 保证参照完整性。
  • 三种关系:一对多(最常见,多方加外键)、一对一(唯一外键)、多对多(中间表拆两个一对多)。
  • 参照完整性:外键值必须存在于被引用主键,不能引用不存在的对象。
  • 外键有代价:检查开销 + 级联风险,高并发系统可能改应用层保证一致性。

第 2 章结束。概念地基铺好了,下一章开始写真正的查询语句——SELECT。

常见疑问

Q1:主键必须用自增整数吗?

不是必须,但很常见。自增整数小而快,适合大多数场景。有些场景用业务唯一键当主键(如身份证号、手机号),但业务键可能变更、可能泄露,长期看不如代理主键稳定。另一种是 UUID,适合分布式环境,缺点是占空间大、索引效率略低。入门阶段建议先用自增整数,理解原理后再按需选型。

Q2:外键约束一定要加吗?

从数据一致性角度,建议加。外键约束让数据库替你保证"不能引用不存在的行",避免脏数据。缺点是每次插入/删除要检查,性能略降;高并发系统有时为了性能去掉外键,改在应用层保证一致性——但那是高级场景的权衡,初学者先把外键用起来。

Q3:怎么理解"多对多"一定需要中间表?

因为关系模型里,一行只能存一个外键指向一个对象。学生和课程是多对多:一个学生有多门课,一门课有多个学生。无论把外键放哪张表都无法表达。所以建一张"选课表",每行存一对(学生ID,课程ID),把多对多拆成两个一对多。这是关系数据库最经典的设计模式,务必理解。

Q4:ON DELETE CASCADE 到底要不要用?

谨慎。CASCADE 会自动删子表数据,方便但危险——误删一行可能连锁删掉几十行。建议默认不用,明确知道"删父必删子"的强关联场景(如订单明细跟随订单删除)才用。生产环境更常见的做法是软删除或限制删除。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U