I'm using a link table to represent a many-to-many relationship as follows (slightly modified for my use case from this previous answer):
CREATE TABLE owner(
owner_id uuid DEFAULT gen_random_uuid(),
PRIMARY KEY(owner_id)
);
CREATE TABLE product(
product_id uuid DEFAULT gen_random_uuid(),
owner_id uuid NOT NULL,
PRIMARY KEY(product_id)
FOREIGN KEY(owner_id) REFERENCES owner(owner_id)
);
CREATE TABLE bill(
bill_id uuid DEFAULT gen_random_uuid(),
owner_id uuid NOT NULL,
PRIMARY KEY(bill_id),
FOREIGN KEY(owner_id) REFERENCES owner(owner_id)
);
CREATE TABLE bill_product(
bill_id uuid,
product_id uuid,
PRIMARY KEY(bill_id, product_id),
FOREIGN KEY(bill_id) REFERENCES bill(bill_id),
FOREIGN KEY(product_id) REFERENCES product(bill_id)
);
This will of course allow a given bill
to belong to many product
s and vice versa. However, I am wondering what the best way is to ensure that the bill
and product
belong to the same owner
.
I see two options:
Trigger - Have the owner
of the bill
and product
checked BEFORE INSERT
, e.g.
CREATE OR REPLACE FUNCTION verify_bill_product_owner() RETURNS trigger AS $trg$
BEGIN
IF (SELECT owner_id FROM product WHERE product_id = NEW.product_id)
<>
(SELECT owner_id FROM bill WHERE bill_id = NEW.bill_id)
THEN
RAISE EXCEPTION 'bill and product do not belong to different owners';
END IF;
RETURN NEW;
END
$trg$ LANGUAGE plpgsql;
CREATE TRIGGER tr_bill_product_biu
BEFORE INSERT OR UPDATE on bill_product
FOR EACH ROW
EXECUTE PROCECURE verify_bill_product_owner();
Compound foreign key - Add the owner_id
to the bill_product
table and have something like:
-- ..
owner_id uuid,
FOREIGN KEY(owner_id, bill_id) REFERENCES bill(owner_id, bill_id),
FOREIGN KEY(owner_id, product_id) REFERENCES product(product_id, product_id),
-- ..
I think both would work I'm just wondering which is most idiomatic and which would work best in a multi-client/session environment.
I'm using Postgres 9.4.2 :-)