这是 SQLite 的外键约束编辑界面(看起来像 Navicat 或 DB Browser for SQLite),我结合你的管线代码表/图层表场景逐项解释。
一、响应(ON UPDATE / ON DELETE 的联动动作)
这三个复选框分别控制三种触发时机,右边下拉框选触发后执行什么动作。
三个复选框的含义
| 选项 | 含义 |
|---|---|
| ON UPDATE | 当被引用表(图层表)的主键/唯一字段被修改时触发。比如把ys_point改名叫ys_pipe_point。 |
| ON DELETE | 当被引用表(图层表)的记录被删除时触发。比如删掉ys_point这一行。 |
| MATCH | SQLite 实际支持有限,一般不用勾选。它控制复合外键多列匹配规则,你是单列外键,留空即可。 |
右边下拉框的 5 种动作(重点)
| 动作 | 含义 | 你的管线场景举例 | 推荐度 |
|---|---|---|---|
| NO ACTION | 不做任何特殊处理,只要子表(代码表)还有引用这条记录的数据,就阻止 UPDATE/DELETE。行为和不写这个子句基本一样。 | 图层表里删ys_point,但代码表里还有101101指向它 → 直接报错,删不掉。 | ✅ 默认最安全 |
| RESTRICT | 和 NO ACTION 几乎一样,也是阻止删除/修改。区别在于触发时机:RESTRICT 更早(约束检查更早执行)。日常用起来没区别。 | 同上 | ✅ 和 NO ACTION 二选一即可 |
| CASCADE | 级联:主表改了/删了,子表跟着改/删。 | 图层表把ys_point改名为ys_pipe_point→ 代码表里所有指向ys_point的记录自动同步改成ys_pipe_point。或者删掉图层表ys_point→ 代码表里所有引用它的行整行被删除。 | ⚠️ UPDATE 改名字很实用;DELETE 级联删数据很危险,慎用 |
| SET NULL | 主表记录被删/改时,子表外键字段设为NULL。 | 图层表删掉ys_point→ 代码表里101101的图层字段自动变成空。不会删行。 | ✅ 推荐用这个做 ON DELETE |
| SET DEFAULT | 主表记录被删/改时,子表外键字段设为列的默认值。 | 前提是代码表的图层字段设了 DEFAULT ‘unknown’,删图层后自动填成unknown。SQLite 对这个支持很弱,基本不用。 | ❌ 不推荐 |
给你的场景推荐配置
结合你之前说的"1个代码对应1个图层":
- ON UPDATE 选 CASCADE:图层标识改名时,代码表自动跟着改,不用手动批量刷。
- ON DELETE 选 SET NULL:图层删了,代码表那条要素的图层字段变空,而不是把整条要素代码记录删掉(删要素代码是要命的)。
对应建表语句就是:
FOREIGNKEY(图层)REFERENCES图层表(图层标识)ONUPDATECASCADE-- 图层改名,代码表自动同步ONDELETESETNULL-- 图层删除,代码表图层字段置空⚠️ 注意:如果代码表的图层字段设了 NOT NULL,ON DELETE SET NULL 会报错。你的场景允许图层为空的话就别加 NOT NULL。
二、延迟外键约束(DEFERRABLE)
这两个下拉框控制外键检查在什么时候执行。SQLite 里对应两个子句:
第一个下拉框:DEFERRABLE(是否可延迟)
| 选项 | 含义 |
|---|---|
| DEFERRABLE | 约束可以被推迟,到事务提交时才检查。 |
| NOT DEFERRABLE | 约束不能推迟,每条 INSERT/UPDATE/DELETE 语句执行完立刻检查。 |
第二个下拉框:INITIALLY(初始模式)
| 选项 | 含义 |
|---|---|
| INITIALLY DEFERRED | 事务提交时才检查外键。 |
| INITIALLY IMMEDIATE | 每条语句执行时就检查(默认行为)。 |
实际意义(结合你的场景)
这个功能主要解决插入顺序问题:
- 默认(NOT DEFERRABLE / IMMEDIATE):必须先插图层表,再插代码表。如果你先插代码表写了
ys_point,但图层表还没这行,立刻报错。 - DEFERRABLE INITIALLY DEFERRED:你可以在一个事务里先插代码表,再插图层表,只要提交事务时两边数据对上就行。
你需要用吗?
基本不用管,保持默认即可。
你的码表是标准配置数据,录入流程本来就是先配图层、再录要素代码,顺序天然合理。延迟外键主要用于:
- 数据迁移/导入时批量倒数据,顺序不好控制
- 复杂事务里多张表互相引用(A 引用 B,B 又引用 A),不延迟就插不进去
普通业务系统保持默认(NOT DEFERRABLE / IMMEDIATE)就对了。
总结一张图
外键约束 ├── 引用表/引用列:图层表.图层标识(被引用的目标) ├── 响应(主表变动时子表怎么办) │ ├── ON UPDATE(主表主键被修改时) │ │ └── 推荐 CASCADE —— 图层改名,代码表自动同步 │ ├── ON DELETE(主表记录被删除时) │ │ └── 推荐 SET NULL —— 图层删了,代码表图层字段变空 │ └── MATCH(复合外键匹配规则,单列外键不勾) └── 延迟外键约束(什么时候检查外键) ├── DEFERRABLE?默认 NOT DEFERRABLE └── INITIALLY?默认 IMMEDIATE └── 普通业务不用改,保持默认还有什么不清楚的地方可以继续问。