Re: Foreign Key normalization question - Mailing list pgsql-general
From | D. Dante Lorenso |
---|---|
Subject | Re: Foreign Key normalization question |
Date | |
Msg-id | 48BDB19D.4020101@lorenso.com Whole thread Raw |
In response to | Re: Foreign Key normalization question (Matthew Wilson <matt@tplus1.com>) |
List | pgsql-general |
Matthew Wilson wrote: > On Tue 02 Sep 2008 04:40:55 PM EDT, Scott Marlowe wrote: >> On Tue, Sep 2, 2008 at 2:35 PM, Matthew Wilson <matt@tplus1.com> wrote: >>> On Tue 02 Sep 2008 04:19:41 PM EDT, Scott Marlowe wrote: >>>> If the two subordinate tables ALWAYS have to point to the same place, >>>> why two tables? Can't a customer have > 1 location? I'm pretty sure >>>> IBM has more than one corporate office you could ship things to. >>> Yeah, so the idea is one customer might have many locations and many >>> products. And at each location, some subset of all their products is >>> available. >> You could have the product_locations have a custid1 and custid2 fields >> that reference the two parent tables, and then a check constraing on >> product_locations that custid1=custid2 > > You inspired me to change my tables to this: > > create table location ( > id serial unique, > name text, > customer_id int references customer, > primary key (id, customer_id) > ); > > create table product ( > id serial unique, > name text, > customer_id int references customer, > primary key (id, customer_id) > ); > > create table product_location ( > product_id int references product (id), > product_customer_id int references customer (id), > location_id int references location (id), > location_customer_id int references customer (id) check product_customer_id = location_customer_id, > foreign key (product_id, product_customer_id) references product (id, customer_id), > foreign key (location_id, location_customer_id) references location (id, customer_id), > ); > > This seems to work based on my informal testing, but it seems really > byzantine. I wish I didn't have to explicitly put the customer IDs in > the table. > > Is there a better way? You could add a trigger to your product_location table that just double-checked the customers matched or prevents the insert/update. A PL/PGSQL function like this might help: ---------- 8< -------------------- 8< ---------- DECLARE is_ok BOOLEAN; BEGIN SELECT p.customer_id = l.customer_id INTO is_ok FROM product p, location l WHERE p.product_id = NEW.product_id AND l.location_id = NEW.location_id; -- didnt find the product and location ... weird IF NOT FOUND THEN RETURN NULL; END; -- product customer matches the location customer IF is_ok = TRUE THEN RETURN NEW; END; -- product and location customers did NOT match, reject changes RETURN NULL; END; ---------- 8< -------------------- 8< ---------- Disclaimer: I have no idea if that code works. I just whipped it up now without testing it. That might do your checks without having to add columns to tables you don't want to add. Good luck. -- Dante
pgsql-general by date: