SQlite:外键约束

目录

先看一个没有外键的"混乱场景"

外键约束:给表之间加"联动规则"

[1. 确定"父表"和"子表"](#1. 确定“父表”和“子表”)

[2. 外键的核心作用:拦截"无效关联"](#2. 外键的核心作用:拦截“无效关联”)

[关键:外键动作(ON DELETE / ON UPDATE)怎么用?](#关键:外键动作(ON DELETE / ON UPDATE)怎么用?)

面试必知:SQLite外键需要手动启用!

总结:外键是"表关系的守护神"


先看一个没有外键的"混乱场景"

假设公司有两张表:

  • Departments(部门表):存部门ID和部门名(比如研发部、市场部);

  • Employees(员工表):存员工ID、姓名、所属部门ID。

如果没有外键约束,会出现这些问题:

  1. 员工属于"不存在的部门" :比如员工表中存了dept_id=99,但部门表中根本没有99号部门,这个员工就成了"无所属部门的幽灵员工";

  2. 删除部门后,员工信息成垃圾 :比如研发部(dept_id=1)被删除了,但员工表中还有很多dept_id=1的员工,这些员工的部门信息永远无效了;

  3. 部门ID改了,员工信息没同步 :比如研发部ID从1改成100,但员工表中还是dept_id=1,导致所有研发部员工"找不到部门"。

外键约束的作用,就是通过规则避免这些混乱,保证"部门"和"员工"的关联永远有效。

外键约束:给表之间加"联动规则"

以上面的部门和员工表为例,外键约束会这样工作:

1. 确定"父表"和"子表"
  • 父表:Departments(部门是"主",员工依赖部门存在);

  • 子表:Employees(员工是"从",所属部门必须在父表中存在);

  • 外键列:员工表的dept_id(这个值必须对应父表Departmentsdept_id)。

创建表时定义外键:

复制代码
-- 父表:部门表(有主键dept_id)
CREATE TABLE Departments (
    dept_id INTEGER PRIMARY KEY,
    dept_name TEXT NOT NULL -- 部门名不能为空
);

-- 子表:员工表(外键关联部门表)
CREATE TABLE Employees (
    emp_id INTEGER PRIMARY KEY,
    name TEXT,
    dept_id INTEGER, -- 外键列:关联部门ID
    -- 外键约束:员工的dept_id必须在Departments表的dept_id中存在
    FOREIGN KEY (dept_id) REFERENCES Departments (dept_id)
        ON DELETE SET NULL  -- 部门删除时,员工的dept_id设为NULL
        ON UPDATE CASCADE   -- 部门ID更新时,员工的dept_id同步更新
);
2. 外键的核心作用:拦截"无效关联"
  • 当你想往员工表插入dept_id=99(但部门表没有99)时,数据库会直接报错,拒绝插入------避免"幽灵员工";

  • 当你想删除部门表中dept_id=1(但员工表还有人属于这个部门)时,外键会按规则处理(比如上面的ON DELETE SET NULL会把员工的dept_id改成NULL,而不是允许删除后留垃圾数据)。

关键:外键动作(ON DELETE / ON UPDATE)怎么用?

这是面试高频考点,结合场景理解四种常用规则:

动作 场景举例(部门表操作后,员工表如何联动)
RESTRICT(默认) 如果研发部(dept_id=1)还有员工,就禁止删除研发部("先清员工,才能删部门")。适合不允许"部门下有员工时删部门"的场景(比如重要部门)。
SET NULL 研发部被删除后,所有原研发部员工的dept_id变成NULL("部门没了,员工暂归无部门")。适合部门可删除,但员工信息需保留的场景。
CASCADE 研发部ID从1改成100 → 所有员工的dept_id自动从1改成100;删除研发部 → 所有研发部员工也被删除("部门没了,员工也一起清")。适合临时项目部门(项目结束,部门和员工记录一起删)。
SET DEFAULT 提前给员工表的dept_id设默认值(比如0代表"待分配"),删除部门后,员工dept_id自动变成0。适合需要明确"无部门员工归到默认组"的场景。

面试必知:SQLite外键需要手动启用!

和其他数据库(如MySQL)不同,SQLite的外键约束默认可能关闭(尤其是旧版本)。所以在连接数据库后,必须先执行一句命令开启外键:

复制代码
PRAGMA foreign_keys = ON; -- 开启外键约束(关键!面试说出来加分)

如果没开,外键约束会失效,上面的所有规则都不会生效(这是很多人踩过的坑)。

总结:外键是"表关系的守护神"

它通过三个层面保证数据有效:

  1. 插入时:子表不能引用父表不存在的数据(拦截幽灵员工);

  2. 删除时:按规则处理子表关联数据(避免垃圾数据);

  3. 更新时:同步子表关联字段(避免关联断裂)。

面试时结合"部门-员工""订单-商品"等场景举例,再提一句"记得用PRAGMA开启外键",会显得你既懂原理又有实战经验~

相关推荐
金仓拾光集8 小时前
金仓替代MongoDB:安全与性能协同提升——社交用户画像系统的国产化实践
数据库·安全·mongodb·kingbase·kingbasees·数据库平替用金仓·金仓数据库
FinTech老王8 小时前
国产数据库替换MongoDB实战:浙江人民医院电子病历系统国产化升级案例
数据库·mongodb
l1t8 小时前
在Lua用luasql-sqlite3库访问SQLite数据库
数据库·git·sqlite·lua
2501_938780288 小时前
《轨道交通检测系统中 Qt 与数据库交互的优化方案》
数据库·qt·交互
qqxhb8 小时前
系统架构设计师备考第61天——嵌入式系统架构模式&操作系统&数据库&中间件
数据库·中间件·系统架构·sqlite·dds·层次化(封闭/开放)·递归模式
SelectDB9 小时前
Apache Doris 数据导入原理与性能优化 | Deep Dive
运维·数据库·数据分析
悟能不能悟9 小时前
在service方法中已经catch异常,Transactional失效怎么办
java·数据库·sql
月夜奇术师9 小时前
SQL查询性能优化:从30分钟到30秒的蜕变——破解串行查询瓶颈
数据库·性能优化
zimoyin10 小时前
解决导入的数据库中因为 sql_mode 不同 视图无法打开问题
数据库·sql