SQL-外键

🚀 SQL 外键

引言

在关系型数据库设计中,外键(Foreign Key)是建立表间关联的核心机制。

一、外键的本质:不是列名,而是约束

核心定义
外键是表中用于关联另一张表的列,但关联通过外键约束(Foreign Key Constraint)实现,而非仅靠列名。
示例
在学生表students中添加class_id列关联班级表classes的主键id

-- 添加外键约束
ALTER TABLE students
ADD CONSTRAINT fk_class_id  -- 约束名称可自定义
FOREIGN KEY (class_id)       -- 声明外键列
REFERENCES classes (id);     -- 关联目标表的主键

关键点

  • 约束可防止无效数据插入(如class_id=99classes表无此班级)。
  • 实际开发中,因性能考量(约束会增加数据库开销),常仅通过应用逻辑保证关联正确性,此时class_id只是普通列,但逻辑上仍是外键。

二、表间关系的三种形态

1. 一对多(最常用)

场景:一个班级对应多个学生(classes → students)。
实现
在「多」的一方(students表)添加外键列class_id,指向「一」方(classes表)的主键id
数据示例

-- classes表(一)
id | name
1  | 一班
2  | 二班

-- students表(多)
id | class_id | name
1  | 1        | 小明
2  | 1        | 小红
3  | 2        | 小白

2. 多对多(需中间表)

场景:一个老师可教多个班级,一个班级可有多个老师(teachers ↔ classes)。
实现
创建中间表teacher_class,包含两个外键列teacher_idclass_id,分别关联两张表的主键。
数据示例

-- teachers表
id | name
1  | 张老师
2  | 王老师

-- classes表
id | name
1  | 一班
2  | 二班

-- 中间表 teacher_class
id | teacher_id | class_id
1  | 1          | 1
2  | 1          | 2
3  | 2          | 1

核心逻辑:通过中间表,将多对多拆解为两个一对多(teachersteacher_classclassesteacher_class)。

3. 一对一(可拆可合)

场景

  • 学生联系方式(students ↔ contacts):部分学生无手机号,可将联系方式单独存表。
  • 大表拆分(如用户基本信息user_info ↔ 详细信息user_profiles):提升查询性能。
    实现
    在关联表中添加外键列(如contacts表的student_id),指向主表主键,且保证唯一。
    数据示例
-- students表
id | name
1  | 小明

-- contacts表(一对一)
id | student_id | mobile
1  | 1          | 135xxxx6300

注意:一对一关系可直接合并为一张表,拆分需根据业务需求(如避免空值、优化查询)决定。

三、外键约束的增删操作

1. 删除外键约束

ALTER TABLE students
DROP FOREIGN KEY fk_class_id;  -- 删除约束,但保留class_id列

2. 删除外键列(非约束)

ALTER TABLE students
DROP COLUMN class_id;  -- 彻底删除列

四、实战避坑指南

💡 为什么互联网应用常不启用外键约束?

  • 性能原因:约束会增加插入 / 更新数据时的校验开销,影响高并发场景性能。
  • 替代方案:通过应用层逻辑(如接口参数校验、事务控制)保证数据一致性。

⚠️ 多对多中间表的设计要点

  • 中间表至少包含两个外键列,可根据需求添加额外字段(如老师授课时间start_time)。
  • 中间表的两个外键通常组合为联合主键,或单独设置自增主键。

📌 一对一拆分表的适用场景

  • 字段使用率差异大:高频字段放主表,低频字段放从表。
  • 数据完整性要求低:允许从表记录缺失(如可选填写的用户资料)。

五、总结

  • 外键的核心作用:定义表间关系,实现数据关联。
  • 三种关系的本质:一对多是基础,多对多靠中间表,一对一可灵活拆分。
  • 工程权衡:约束 vs 性能,需根据业务场景选择合适的实现方式。

一句话口诀

一对多,外键直接加;多对多,中间表来搭;一对一,拆合看需求,约束性能要权衡!