SQL 外键(Foreign Key)详细讲解

1. 什么是外键?​​
  • ​定义​ :外键是数据库表中的一列(或一组列),用于​建立两个表之间的关联关系​。外键的值必须匹配另一个表的主键(Primary Key)或唯一约束(Unique Constraint)的值。
  • ​作用​ :
    • 确保数据的​引用完整性​(Referential Integrity),防止无效数据插入。
    • 维护表之间的逻辑关系(如"一对多"或"多对多")。

​​2. 外键的语法​​

在创建表时定义外键:

复制代码
CREATE TABLE 子表 (
    列1 数据类型,
    列2 数据类型,
    ...
    FOREIGN KEY (外键列) REFERENCES 父表(主键列)
    [ON DELETE 约束行为] [ON UPDATE 约束行为]
);

在已有表中添加外键:

复制代码
ALTER TABLE 子表
ADD CONSTRAINT 约束名称
FOREIGN KEY (外键列) REFERENCES 父表(主键列)
[ON DELETE 约束行为] [ON UPDATE 约束行为];

​​3. 外键的约束行为​​

当父表的记录被删除或更新时,子表的外键如何处理?通过 ON DELETE 和 ON UPDATE 指定:

约束行为 说明
​​CASCADE​​ 级联操作。父表删除/更新记录时,子表关联记录也被删除/更新。
​​SET NULL​​ 父表删除/更新记录时,子表的外键列设为 NULL(要求外键列允许 NULL)。
​​NO ACTION​​ 默认行为。阻止父表的删除/更新操作,如果子表存在关联记录。
​​RESTRICT​​ 类似 NO ACTION,立即检查约束。
​​SET DEFAULT​​ 父表删除/更新记录时,子表的外键设为默认值(需定义默认值)。

​​4. 多列外键​​

外键可以由多个列组成,需满足:

  • 子表和父表的列数、顺序、数据类型一致。
  • 父表的列必须有唯一约束(如主键或唯一索引)。

​​示例​​:

复制代码
CREATE TABLE 订单详情 (
    订单ID INT,
    产品ID INT,
    数量 INT,
    PRIMARY KEY (订单ID, 产品ID),
    FOREIGN KEY (订单ID) REFERENCES 订单(订单ID),
    FOREIGN KEY (产品ID) REFERENCES 产品(产品ID)
);

​​5. 外键的限制与注意事项​​
  1. ​父表必须有主键或唯一约束​。
  2. ​外键列的数据类型必须与父表主键一致​。
  3. ​引擎支持​:如 MySQL 的 InnoDB 支持外键,而 MyISAM 不支持。
  4. ​性能影响​:外键会增加数据操作的检查开销,但能提升数据一致性。
  5. ​循环依赖​:避免两个表互相引用。

​​6. 实际应用示例​​

​​场景​ ​:学生表(students)和课程表(courses),通过选课表(enrollments)关联。

复制代码
-- 父表:学生表
CREATE TABLE students (
    student_id INT PRIMARY KEY,
    name VARCHAR(50)
);

-- 父表:课程表
CREATE TABLE courses (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(50)
);

-- 子表:选课表(含外键)
CREATE TABLE enrollments (
    student_id INT,
    course_id INT,
    enrollment_date DATE,
    FOREIGN KEY (student_id) REFERENCES students(student_id) ON DELETE CASCADE,
    FOREIGN KEY (course_id) REFERENCES courses(course_id) ON DELETE RESTRICT
);

​​插入数据​​:

复制代码
-- 插入学生和课程
INSERT INTO students VALUES (1, 'Alice');
INSERT INTO courses VALUES (101, 'Math');

-- 合法插入:学生和课程存在
INSERT INTO enrollments VALUES (1, 101, '2023-10-01');

-- 非法插入:学生不存在,触发外键错误
INSERT INTO enrollments VALUES (999, 101, '2023-10-01'); -- 报错!

​​7. 常见问题​​
  1. ​​外键必须指向主键吗?​ ​

    不,可以指向父表的唯一约束(Unique Constraint)。

  2. ​​能否跨数据库引用?​ ​

    通常不支持,外键需在同一数据库内。

  3. ​​外键是否允许 NULL?​ ​

    如果外键列允许 NULL,则插入 NULL 是合法的(表示无关联)。

  4. ​​如何查看外键约束?​ ​

    使用数据库工具或查询元数据(如 MySQL 的 SHOW CREATE TABLE)。


​​8. 总结​​
  • ​外键的核心作用​:维护数据的一致性和关联性。
  • ​适用场景​:需要强数据完整性的系统(如电商、金融)。
  • ​慎用场景​:高并发写入且对性能要求极高的系统(需权衡一致性与性能)。
相关推荐
数据库小学妹5 小时前
MySQL大字段治理:行溢出机制、覆盖索引与拆表
数据库·mysql·性能优化
爱吃奥利奥_wen5 小时前
SQL Server 基础语法详解:从建库建表到约束与增删改查
服务器·数据库·oracle
这个DBA有点耶6 小时前
MySQL 8.0不可见索引:删索引怕出事,不删又拖慢写入——中间态怎么用?
数据库·mysql·代码规范
测试界的小码农7 小时前
【图数据库实战进阶(01):从零认识 Neo4j,搭建第一个图数据库项目】
数据库·neo4j
x_SpiderMan8 小时前
搭建Oracle RAC 集群
数据库·oracle
测试界的小码农8 小时前
【图数据库实战进阶(03):Neo4j 图数据建模实战——节点、关系与属性应该怎么设计?】
数据库·oracle·neo4j
瑞克-桑切斯8 小时前
redis
数据库·redis·缓存
freejackman9 小时前
【工程化】从“单兵作战”到“多引擎架构”:基于门面模式的重构实战
大数据·数据库·hive·sql·测试工具·设计模式·架构
bksczm9 小时前
InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer
数据库·mysql
花间相见9 小时前
【计算基础|Redis02】【上手】五大数据类型命令逐条实操
数据库·redis·后端