如何确保不相关表之间的完整性?

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_idtype_id -(复合 PK)coy_id -(FK引用 COY.coy_id)type_id - (FK 引用 ins_type.type_id)

订阅naf_notype_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。伟大的解决方案!我想我更喜欢使用触发器,因为我正在尽可能地避免冗余。但是,我从未使用过触发器。那么,如何使用触发器来实现呢? 我添加了一个例子,希望对您有所帮助。

以上是关于如何确保不相关表之间的完整性?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL详细介绍,设置oracle相关

Rails 方法用于两个相关连接表之间的关系并同时强制数据完整性

我们如何确保 mongoDb 中的数据完整性?

约束条件 ,表与表之间的关系 和多表联合查询***

如何使用 TLS/SSL 确保 WebSocket 连接的安全

如何使用 TLS/SSL 确保 WebSocket 连接的安全