外键约束:分表一对一关系替代方案 无需子表type列避免book_id重复
可行的实现方案有以下几种,可以根据业务场景选择:
1. 数据库触发器校验(最稳妥的数据库层方案)
给AudioBook和PaperBook分别添加BEFORE INSERT、BEFORE UPDATE触发器,触发逻辑如下:
- 往
AudioBook插入/修改book_id时:- 先查询
Book表对应id的type是否为audio,不符合就抛出错误中断操作 - 再查询
PaperBook表是否已存在当前book_id,存在则抛出错误
- 先查询
- 给
PaperBook加对称的触发器逻辑即可。
这种方案完全在数据库层面实现,不需要修改现有表结构,也能堵住直接操作数据库绕过校验的漏洞。
2. 业务逻辑层统一校验
如果你的业务所有对子表的写操作都走统一的服务层入口,可以直接在代码层面加校验逻辑,每次写入子表前先查询父表类型、检查另一个子表是否有重复book_id,不符合就拦截操作。
这种方案实现最简单,不需要修改数据库逻辑,但无法限制直接操作数据库的行为,适合没有直接改库权限的生产环境。
3. 物化视图加唯一约束
创建一个物化视图,内容是两个子表book_id的并集:
CREATE MATERIALIZED VIEW book_id_unique_check AS SELECT book_id FROM AudioBook UNION ALL SELECT book_id FROM PaperBook;
然后给这个物化视图的book_id字段加唯一索引:
CREATE UNIQUE INDEX idx_unique_book_id ON book_id_unique_check(book_id);
每次写入子表后刷新物化视图即可触发校验,适合写入频率较低的场景。
内容的提问来源于stack exchange,提问作者ZiiMakc
相关产品推荐
相关产品推荐

