← [ BACK_TO_NOTES ]

外键

外键用于表达表与表之间的引用关系,并由数据库维护引用完整性。

#concept #growing #backend #database #sql

[!info] related notes

外键

一句话定义

外键是数据库中的引用约束:它要求子表中的引用值必须对应父表中真实存在的候选键,从而维护引用完整性。

核心机制

CREATE TABLE assessments (
  id BIGINT PRIMARY KEY,
  user_id BIGINT NOT NULL,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

这里:

assessments.user_id
        ↓ references
users.id

如果不存在 users.id = 999,那么插入 user_id = 999 的 Assessment 会被数据库拒绝。

外键的价值不是 JOIN

两个概念职责不同:

FOREIGN KEY
→ 保证持久化关系合法

JOIN
→ 查询时把多张表组合起来

即使没有真正创建外键,也能写 JOIN;反过来,有外键也不代表每次查询都要 JOIN。

应用预检查与数据库最终约束

Service 可以先查询:

User 是否存在?

以便返回友好的业务错误。但只靠“先查再插”存在并发时间窗:检查成功后,父记录可能被另一个事务删除。

因此更稳的分工是:

Application
→ 提前校验、表达业务语义

Database FK
→ 最终守住引用完整性

删除父记录时怎么办

外键还要定义父记录删除后的生命周期策略:

RESTRICT / NO ACTION

仍被引用时拒绝删除父记录。

CASCADE

删除父记录时自动删除引用它的子记录。

SET NULL

保留子记录,但把外键设为 NULL;对应列必须允许为空。

选择哪种策略取决于领域生命周期,而不是哪种写法更省代码。

更新与索引边界

  • 外键还可以定义 ON UPDATE 行为,但稳定代理主键通常很少修改。
  • PostgreSQL 不会因为创建外键就自动为“引用方外键列”创建索引;如果经常按 user_id 查询或删除父记录需要检查大量子行,通常应结合访问模式考虑索引。

边界与易混淆点

  • 外键不等于“子表主键”;在 1:N 中,同一个 user_id 正常情况下会重复多次。
  • 外键能表达数据库可见的引用规则,但不能替代“当前登录用户是否有权限操作资源”这类 Authorization。
  • 有些系统出于跨库、分片或写入架构原因不启用物理外键,但这意味着引用完整性需要由其他机制承担,而不是关系约束不重要。
创建于 2026/5/5 更新于 2026/9/14
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本