views:

103

answers:

2

I have two parent tables, BusinessGroup and SocialGroup, and one child table, Members. A Member can belong to either parent, but not both.

As far as I can see, there are two options for constructing the child table.

Opt 1: Include a field for ParentType, and another for ParentID. The ParentType would be an enum (Business, Social) and the ParentID would be the PK from the respective parent table.

Opt 2: Include a field for BusinessGroupID, and another for SocialGroupID. In this case, the fields would need to be nullable, and only one could contain a value.

Any ideas on which approach is best?

I tried option 1 in MySQL, and created two foreign keys from the child back to the parents. I ran into trouble when inserting values though, since MySQL was expecting a corresponding value in BOTH parent tables.

As a supplementary question: how do things change if I have a larger number of parents, e.g. 6?

Thanks!

+1  A: 

"parent tables" is probably a misnomer - in the relational model I'd flip your relationship. e.g. make members the master records table, and a join table that allows 1-1 mapping, so have a PK of member_id or whatever the right field is, and map to the FK in either BusinessGroup or SocialGroup.

jayshao
+1  A: 

alt text

CREATE TABLE Group ( 
    GroupID       integer    NOT NULL
  , Name          varchar(18)
  , Description   varchar(18)
  , GroupType     varchar(4) NOT NULL
  -- all columns common to any group type
);
ALTER TABLE Group ADD CONSTRAINT pk_Group PRIMARY KEY (GroupID) ;


CREATE TABLE BusinessGroup ( 
    GroupID   integer NOT NULL
  -- all columns specific to business groups
);
ALTER TABLE BusinessGroup
    ADD CONSTRAINT pk_BusinessGroup  PRIMARY KEY (GroupID)
  , ADD CONSTRAINT fk1_BusinessGroup FOREIGN KEY (GroupID) REFERENCES Group(GroupID) ;


CREATE TABLE SocialGroup ( 
    GroupID    integer NOT NULL
  -- all columns specific to social groups
);
ALTER TABLE SocialGroup
    ADD CONSTRAINT pk_SocialGroup  PRIMARY KEY (GroupID)
  , ADD CONSTRAINT fk1_SocialGroup FOREIGN KEY (GroupID) REFERENCES Group(GroupID) ;


CREATE TABLE Person ( 
    PersonID  integer NOT NULL
  , GroupID   integer NOT NULL
);
ALTER TABLE Person
    ADD CONSTRAINT pk_Person  PRIMARY KEY (PersonID)
  , ADD CONSTRAINT fk1_Person FOREIGN KEY (GroupID) REFERENCES Group(GroupID) ;

.

Damir Sudarevic
Thanks Damir, much appreciated.For anyone else looking for an explanation, have a look at this excellent slideshow from Bill Karwin http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
Kim