You can do it using controlled redundancy and composite FK constraints:
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)
);
I added a composite unique key (offr_id, coy_id) to support a composite FK constraint on the subscribe
table.
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)
);
The composite primary key here is perfect for a composite FK constraint on the subscribe
table.
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)
);
Overlapping composite FK constraints will ensure that an officer can only subscribe to insurance offered by the company he/she is enrolled in. coy_id
is logically redundant but required for integrity and there's no risk of update anomalies due to the FK constraints.
Alternatively, you could use triggers to check that the values are related via inner joins:
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');
Disclaimer: I was unable to test this on SqlFiddle and don't have Oracle installed, but hopefully it'll point you in the right direction.