[Pdx-pm] Eliminating circular table relations.

David E. Wheeler david at kineticode.com
Wed Jan 31 13:33:54 PST 2007


On Jan 31, 2007, at 1:15 PM, Michael G Schwern wrote:

> Let's hear those answers.  I'm building up a case for Postgres here  
> and the more ammo the better.

You build the tables as you described, then you create a view joining  
them as two separate tables, one for meat_account and one for  
mushroom account. Something like this (untested PostgreSQL code):

CREATE TABLE _account (
     id                  SERIAL PRIMARY KEY,
     name                TEXT,
     address             TEXT,
     phone               TEXT
);

# sub-type
CREATE TABLE _meat_account (
     id                  INTEGER PRIMARY KEY REFERENCES account(id),
     drippings           BOOLEAN,
     gravy               TEXT
);

# sub-type
CREATE TABLE _mushroom_account (
     id                  INTEGER PRIMARY KEY REFERENCES account(id),
     type                TEXT
);


CREATE VIEW meat_account AS
SELECT a.id as id, name, address, phone, drippings, gravy
   FROM _account a, _meat_account ma
  WHERE a.id = ma.id;

CREATE VIEW mushsroom_account AS
SELECT a.id as id, name, address, phone, type
   FROM _account a, _mushroom_account ma
  WHERE a.id = ma.id;

Then update preferences so that the user has permission to access  
only the views, and not the tables. Next you create rules on the view  
to handle INSERTS, UPDATES, and DELETES. They look something like this:

CREATE RULE insert_meat_account AS
ON INSERT TO meat_account DO INSTEAD (
   INSERT INTO _account (id, name, address, phone)
   VALUES (NEXTVAL('_account_id_seq'), NEW.name, NEW.address,  
NEW.phone);

   INSERT INTO _meat_account (id, drippings, gravy)
   VALUES (CURRVAL('_account_id_seq'), NEW.drippings, NEW.gravy);
);

Create similar rules ON UPDATE and ON DELETE. Then you can treat the  
views exactly like tables and completely ignore the _account and  
_meat_account tables.

I went into some detail on this approach in presentations at the last  
two OSCONs. I used it to model OO inheritance in the database  
(meat_account inherits from account). You can get the slides here:

   http://conferences.oreillynet.com/presentations/os2006/ 
wheeler_david.pdf
   http://www.kineticode.com/docs/polymorphic_database_design.pdf

I also use it extensively in Object::Relation, my ORM module that I  
expect to get back to hacking sooner or later.

HTH,

David


More information about the Pdx-pm-list mailing list