如何确保不相关表之间的完整性?
Posted
技术标签:
【中文标题】如何确保不相关表之间的完整性?【英文标题】:How do I ensure integrity between unrelated tables? 【发布时间】:2017-04-14 14:25:25 【问题描述】:我最近刚开始学习数据库设计,目前正在使用 Oracle 11G 和 SQL Developer。
我有这 3 个 DB 业务规则:
每位官员必须注册一家且仅一家保险公司。每个保险公司可以招收一名或多名高级职员 每个保险公司必须提供至少五种不同类型的保险类型。每种类型的保险最多可以由 4 家保险公司提供,或者根本不提供。 每种保险类型都可以由一名或多名官员订阅。每个官员最多可以订阅同一家公司提供的五种不同的保险。。 . .
到目前为止,非常好,我想出了五个表(INS_COY、OFFR、INS_TYPE、PROVIDE 和 SUBSCRIBE)。 PROVIDE 和 SUBSCRIBE 是作为复合表出现的,因为 INS_COY 和 INS_TYPE 之间的关系,以及 OFFR 和 INS_TYPE 之间的关系都是 M:M 关系。
各表的PK和FK属性如下:
INS_COY 表coy_id - PK
OFFR TABLEoffr_id - PKcoy_id -(FK 引用 INS_COY.coy_id))
INS_TYPE TABLEtype_id - PK
提供coy_id 和 type_id -(复合 PK)coy_id -(FK引用 COY.coy_id)type_id - (FK 引用 ins_type.type_id)
订阅naf_no 和 type_id -(复合 PK)naf_no -(FK引用 offr.offr_id)type_id (FK 引用 ins_type.type_id)
. . .
表已成功创建,示例数据已插入。
所以,问题是 - 在 SUBSCRIBE 表中,我如何确保附加到 OFFR_ID 的 TYPE_ID 是他注册的 COY 提供的 INS_TYPE 的完整性?
sample data tables
即...从表格中,“offr 4250”注册在“coy 1”中,而“coy 1”不提供“ins_type 13”,但是,因为没有限制检查这一点,“offr 1 " 订阅了 SUBSCRIBE TABLE 上的 "ins_type 13"。
【问题讨论】:
【参考方案1】:您可以使用受控冗余和复合 FK 约束来做到这一点:
CREATE TABLE offr (
offr_id INT NOT NULL,
coy_id INT NOT NULL,
PRIMARY KEY (offr_id),
FOREIGN KEY (coy_id) REFERENCES ins_coy (coy_id),
UNIQUE KEY (offr_id, coy_id)
);
我添加了一个复合唯一键 (offr_id, coy_id) 以支持 subscribe
表上的复合 FK 约束。
CREATE TABLE provide (
coy_id INT NOT NULL,
type_id INT NOT NULL,
PRIMARY KEY (coy_id, type_id),
FOREIGN KEY (coy_id) REFERENCES ins_coy (coy_id)
);
这里的复合主键非常适合 subscribe
表上的复合 FK 约束。
CREATE TABLE subscribe (
naf_no INT NOT NULL,
coy_id INT NOT NULL,
type_id INT NOT NULL,
PRIMARY KEY (naf_no, type_id),
FOREIGN KEY (naf_no, coy_id) REFERENCES offr (offr_id, coy_id),
FOREIGN KEY (coy_id, type_id) REFERENCES provide (coy_id, type_id)
);
重叠的复合 FK 约束将确保军官只能订阅由他/她注册的公司提供的保险。coy_id
在逻辑上是多余的,但对于完整性是必需的,并且不存在由于 FK 约束而导致更新异常的风险.
或者,您可以使用触发器来检查值是否通过内部连接关联:
CREATE TRIGGER check_subscribe BEFORE INSERT OR UPDATE ON subscribe
FOR EACH ROW
WHEN NOT EXISTS (
SELECT 1
FROM offr
INNER JOIN provide ON offr.coy_id = provide.coy_id
WHERE offr.offr_id = new.naf_no AND provide.type_id = new.type_id
)
RAISE_APPLICATION_ERROR (num => -20000, msg => 'Officers can only subscribe to types provided by their company');
免责声明:我无法在 SqlFiddle 上对此进行测试,也没有安装 Oracle,但希望它能为您指明正确的方向。
【讨论】:
谢谢@reaanb。伟大的解决方案!我想我更喜欢使用触发器,因为我正在尽可能地避免冗余。但是,我从未使用过触发器。那么,如何使用触发器来实现呢? 我添加了一个例子,希望对您有所帮助。以上是关于如何确保不相关表之间的完整性?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 方法用于两个相关连接表之间的关系并同时强制数据完整性